@neat.is/core 0.4.4 → 0.4.5
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-YJOA7BBF.js → chunk-3QCRUEQD.js} +2 -2
- package/dist/{chunk-J4YBTD24.js → chunk-6GXBAR3M.js} +3 -3
- package/dist/{chunk-ZVNP3ZDH.js → chunk-HVF4S7J3.js} +6 -3
- package/dist/chunk-HVF4S7J3.js.map +1 -0
- package/dist/{chunk-G3YGPWJL.js → chunk-RBWL4HRB.js} +13 -2
- package/dist/chunk-RBWL4HRB.js.map +1 -0
- package/dist/cli.cjs +161 -32
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +149 -34
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +15 -1
- 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 +4 -4
- package/dist/neatd.cjs +15 -1
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-FIERFRGD.js → otel-grpc-VSPMP3OS.js} +3 -3
- package/dist/server.cjs +15 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-G3YGPWJL.js.map +0 -1
- package/dist/chunk-ZVNP3ZDH.js.map +0 -1
- /package/dist/{chunk-YJOA7BBF.js.map → chunk-3QCRUEQD.js.map} +0 -0
- /package/dist/{chunk-J4YBTD24.js.map → chunk-6GXBAR3M.js.map} +0 -0
- /package/dist/{otel-grpc-FIERFRGD.js.map → otel-grpc-VSPMP3OS.js.map} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -301,12 +301,15 @@ function parseOtlpRequest(body) {
|
|
|
301
301
|
const out = [];
|
|
302
302
|
for (const rs of body.resourceSpans ?? []) {
|
|
303
303
|
const resourceAttrs = attrsToRecord(rs.resource?.attributes);
|
|
304
|
-
const
|
|
304
|
+
const rawServiceName = resourceAttrs["service.name"];
|
|
305
|
+
const resourceServiceNamePresent = typeof rawServiceName === "string" && rawServiceName.length > 0;
|
|
306
|
+
const service = resourceServiceNamePresent ? rawServiceName : "unidentified";
|
|
305
307
|
for (const ss of rs.scopeSpans ?? []) {
|
|
306
308
|
for (const span of ss.spans ?? []) {
|
|
307
309
|
const attrs = attrsToRecord(span.attributes);
|
|
308
310
|
const parsed = {
|
|
309
311
|
service,
|
|
312
|
+
resourceServiceNamePresent,
|
|
310
313
|
traceId: span.traceId ?? "",
|
|
311
314
|
spanId: span.spanId ?? "",
|
|
312
315
|
parentSpanId: span.parentSpanId || void 0,
|
|
@@ -1620,6 +1623,14 @@ function thresholdForEdgeType(edgeType, overrides) {
|
|
|
1620
1623
|
function nowIso(ctx) {
|
|
1621
1624
|
return new Date(ctx.now ? ctx.now() : Date.now()).toISOString();
|
|
1622
1625
|
}
|
|
1626
|
+
var unidentifiedWarnedProjects = /* @__PURE__ */ new Set();
|
|
1627
|
+
function warnUnidentifiedSpan(project) {
|
|
1628
|
+
if (unidentifiedWarnedProjects.has(project)) return;
|
|
1629
|
+
unidentifiedWarnedProjects.add(project);
|
|
1630
|
+
console.warn(
|
|
1631
|
+
`[neatd] span lacked service.name; routed to 'unidentified' in project ${project}; check your OTel SDK config.`
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1623
1634
|
function pickAttr(span, ...keys) {
|
|
1624
1635
|
for (const k of keys) {
|
|
1625
1636
|
const v = span.attributes[k];
|
|
@@ -1874,6 +1885,9 @@ async function handleSpan(ctx, span) {
|
|
|
1874
1885
|
const ts = span.startTimeIso ?? nowIso(ctx);
|
|
1875
1886
|
const nowMs = ctx.now ? ctx.now() : Date.now();
|
|
1876
1887
|
const env = span.env ?? "unknown";
|
|
1888
|
+
if (span.resourceServiceNamePresent === false) {
|
|
1889
|
+
warnUnidentifiedSpan(ctx.project ?? DEFAULT_PROJECT);
|
|
1890
|
+
}
|
|
1877
1891
|
const sourceId = ensureServiceNode(ctx.graph, span.service, env);
|
|
1878
1892
|
const isError = span.statusCode === 2;
|
|
1879
1893
|
cacheSpanService(span, nowMs);
|
|
@@ -6559,22 +6573,40 @@ var OTEL_INIT_CJS = `${OTEL_INIT_HEADER}
|
|
|
6559
6573
|
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
6560
6574
|
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
6561
6575
|
|
|
6562
|
-
require('@opentelemetry/
|
|
6576
|
+
const { NodeSDK } = require('@opentelemetry/sdk-node')
|
|
6577
|
+
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')
|
|
6578
|
+
|
|
6579
|
+
const instrumentations = [getNodeAutoInstrumentations()]
|
|
6580
|
+
__INSTRUMENTATION_BLOCK__
|
|
6581
|
+
new NodeSDK({ instrumentations }).start()
|
|
6563
6582
|
`;
|
|
6564
6583
|
var OTEL_INIT_ESM = `${OTEL_INIT_HEADER}
|
|
6565
6584
|
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
6566
6585
|
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
6567
6586
|
|
|
6568
|
-
|
|
6587
|
+
import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
6588
|
+
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
|
6589
|
+
|
|
6590
|
+
const instrumentations = [getNodeAutoInstrumentations()]
|
|
6591
|
+
__INSTRUMENTATION_BLOCK__
|
|
6592
|
+
new NodeSDK({ instrumentations }).start()
|
|
6569
6593
|
`;
|
|
6570
6594
|
var OTEL_INIT_TS = `${OTEL_INIT_HEADER}
|
|
6571
6595
|
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
6572
6596
|
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'
|
|
6573
6597
|
|
|
6574
|
-
|
|
6598
|
+
import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
6599
|
+
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
|
6600
|
+
|
|
6601
|
+
const instrumentations = [getNodeAutoInstrumentations()]
|
|
6602
|
+
__INSTRUMENTATION_BLOCK__
|
|
6603
|
+
new NodeSDK({ instrumentations }).start()
|
|
6575
6604
|
`;
|
|
6576
|
-
function renderNodeOtelInit(template, serviceName, projectName) {
|
|
6577
|
-
|
|
6605
|
+
function renderNodeOtelInit(template, serviceName, projectName, registrations = []) {
|
|
6606
|
+
const block = registrations.length === 0 ? "" : `
|
|
6607
|
+
${registrations.join("\n")}
|
|
6608
|
+
`;
|
|
6609
|
+
return template.replace(/__SERVICE_NAME__/g, serviceName).replace(/__PROJECT__/g, projectName).replace(/__INSTRUMENTATION_BLOCK__\n?/g, block);
|
|
6578
6610
|
}
|
|
6579
6611
|
function renderEnvNeat(serviceName, projectName) {
|
|
6580
6612
|
return [
|
|
@@ -6606,7 +6638,9 @@ process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projec
|
|
|
6606
6638
|
import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
6607
6639
|
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
|
6608
6640
|
|
|
6609
|
-
|
|
6641
|
+
const instrumentations = [getNodeAutoInstrumentations()]
|
|
6642
|
+
__INSTRUMENTATION_BLOCK__
|
|
6643
|
+
new NodeSDK({ instrumentations }).start()
|
|
6610
6644
|
`;
|
|
6611
6645
|
var NEXT_INSTRUMENTATION_NODE_JS = `${NEXT_INSTRUMENTATION_HEADER}
|
|
6612
6646
|
process.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'
|
|
@@ -6615,10 +6649,15 @@ process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projec
|
|
|
6615
6649
|
const { NodeSDK } = require('@opentelemetry/sdk-node')
|
|
6616
6650
|
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')
|
|
6617
6651
|
|
|
6618
|
-
|
|
6652
|
+
const instrumentations = [getNodeAutoInstrumentations()]
|
|
6653
|
+
__INSTRUMENTATION_BLOCK__
|
|
6654
|
+
new NodeSDK({ instrumentations }).start()
|
|
6619
6655
|
`;
|
|
6620
|
-
function renderNextInstrumentationNode(template, serviceName, projectName) {
|
|
6621
|
-
|
|
6656
|
+
function renderNextInstrumentationNode(template, serviceName, projectName, registrations = []) {
|
|
6657
|
+
const block = registrations.length === 0 ? "" : `
|
|
6658
|
+
${registrations.join("\n")}
|
|
6659
|
+
`;
|
|
6660
|
+
return template.replace(/__SERVICE_NAME__/g, serviceName).replace(/__PROJECT__/g, projectName).replace(/__INSTRUMENTATION_BLOCK__\n?/g, block);
|
|
6622
6661
|
}
|
|
6623
6662
|
var FRAMEWORK_OTEL_INIT_HEADER = "// Generated by `neat init --apply` (ADR-074). OpenTelemetry SDK hook.";
|
|
6624
6663
|
var FRAMEWORK_OTEL_INIT_TS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}
|
|
@@ -6714,6 +6753,18 @@ var SDK_PACKAGES = [
|
|
|
6714
6753
|
{ name: "@opentelemetry/sdk-node", version: "^0.57.0" },
|
|
6715
6754
|
{ name: "@opentelemetry/auto-instrumentations-node", version: "^0.55.0" }
|
|
6716
6755
|
];
|
|
6756
|
+
function detectNonBundledInstrumentations(pkg) {
|
|
6757
|
+
const deps = allDeps(pkg);
|
|
6758
|
+
const out = [];
|
|
6759
|
+
if ("@prisma/client" in deps) {
|
|
6760
|
+
out.push({
|
|
6761
|
+
pkg: "@prisma/instrumentation",
|
|
6762
|
+
version: "^5.0.0",
|
|
6763
|
+
registration: "instrumentations.push(new (require('@prisma/instrumentation').PrismaInstrumentation)())"
|
|
6764
|
+
});
|
|
6765
|
+
}
|
|
6766
|
+
return out;
|
|
6767
|
+
}
|
|
6717
6768
|
var OTEL_ENV = {
|
|
6718
6769
|
// ADR-069 §4 — endpoint moves into the per-package .env.neat (written
|
|
6719
6770
|
// by the apply phase). The envEdits surface stays for the dry-run
|
|
@@ -7004,8 +7055,19 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
7004
7055
|
version: sdk.version
|
|
7005
7056
|
});
|
|
7006
7057
|
}
|
|
7058
|
+
const nonBundled = detectNonBundledInstrumentations(pkg);
|
|
7059
|
+
for (const inst of nonBundled) {
|
|
7060
|
+
if (inst.pkg in existingDeps) continue;
|
|
7061
|
+
dependencyEdits.push({
|
|
7062
|
+
file: manifestPath,
|
|
7063
|
+
kind: "add",
|
|
7064
|
+
name: inst.pkg,
|
|
7065
|
+
version: inst.version
|
|
7066
|
+
});
|
|
7067
|
+
}
|
|
7007
7068
|
const svcName = serviceNodeName(pkg, serviceDir);
|
|
7008
7069
|
const projectName = projectToken(pkg, serviceDir, project);
|
|
7070
|
+
const registrations = nonBundled.map((i) => i.registration);
|
|
7009
7071
|
const generatedFiles = [];
|
|
7010
7072
|
if (!await exists2(instrumentationFile)) {
|
|
7011
7073
|
generatedFiles.push({
|
|
@@ -7020,7 +7082,8 @@ async function planNext(serviceDir, pkg, manifestPath, nextConfigPath, project)
|
|
|
7020
7082
|
contents: renderNextInstrumentationNode(
|
|
7021
7083
|
useTs ? NEXT_INSTRUMENTATION_NODE_TS : NEXT_INSTRUMENTATION_NODE_JS,
|
|
7022
7084
|
svcName,
|
|
7023
|
-
projectName
|
|
7085
|
+
projectName,
|
|
7086
|
+
registrations
|
|
7024
7087
|
),
|
|
7025
7088
|
skipIfExists: true
|
|
7026
7089
|
});
|
|
@@ -7370,55 +7433,73 @@ async function planAstro(serviceDir, pkg, manifestPath, project) {
|
|
|
7370
7433
|
framework: "astro"
|
|
7371
7434
|
};
|
|
7372
7435
|
}
|
|
7373
|
-
async function
|
|
7374
|
-
const pkg = await readPackageJson(serviceDir);
|
|
7375
|
-
const manifestPath = import_node_path40.default.join(serviceDir, "package.json");
|
|
7376
|
-
const project = opts?.project;
|
|
7377
|
-
const empty = {
|
|
7378
|
-
language: "javascript",
|
|
7379
|
-
serviceDir,
|
|
7380
|
-
dependencyEdits: [],
|
|
7381
|
-
entrypointEdits: [],
|
|
7382
|
-
envEdits: [],
|
|
7383
|
-
generatedFiles: []
|
|
7384
|
-
};
|
|
7385
|
-
if (!pkg) return empty;
|
|
7436
|
+
async function findFrameworkDispatch(serviceDir, pkg, manifestPath, project) {
|
|
7386
7437
|
if (hasNextDependency(pkg)) {
|
|
7387
7438
|
const nextConfig = await findNextConfig(serviceDir);
|
|
7388
7439
|
if (nextConfig) {
|
|
7389
|
-
return planNext(serviceDir, pkg, manifestPath, nextConfig, project);
|
|
7440
|
+
return () => planNext(serviceDir, pkg, manifestPath, nextConfig, project);
|
|
7390
7441
|
}
|
|
7391
7442
|
}
|
|
7392
7443
|
if (hasRemixDependency(pkg)) {
|
|
7393
7444
|
const remixEntry = await findRemixEntry(serviceDir);
|
|
7394
7445
|
if (remixEntry) {
|
|
7395
|
-
return planRemix(serviceDir, pkg, manifestPath, remixEntry, project);
|
|
7446
|
+
return () => planRemix(serviceDir, pkg, manifestPath, remixEntry, project);
|
|
7396
7447
|
}
|
|
7397
7448
|
}
|
|
7398
7449
|
if (hasSvelteKitDependency(pkg)) {
|
|
7399
7450
|
const hooks = await findSvelteKitHooks(serviceDir);
|
|
7400
7451
|
const config = await findSvelteKitConfig(serviceDir);
|
|
7401
7452
|
if (hooks || config) {
|
|
7402
|
-
return planSvelteKit(serviceDir, pkg, manifestPath, hooks, project);
|
|
7453
|
+
return () => planSvelteKit(serviceDir, pkg, manifestPath, hooks, project);
|
|
7403
7454
|
}
|
|
7404
7455
|
}
|
|
7405
7456
|
if (hasNuxtDependency(pkg)) {
|
|
7406
7457
|
const nuxtConfig = await findNuxtConfig(serviceDir);
|
|
7407
7458
|
if (nuxtConfig) {
|
|
7408
|
-
return planNuxt(serviceDir, pkg, manifestPath, project);
|
|
7459
|
+
return () => planNuxt(serviceDir, pkg, manifestPath, project);
|
|
7409
7460
|
}
|
|
7410
7461
|
}
|
|
7411
7462
|
if (hasAstroDependency(pkg)) {
|
|
7412
7463
|
const astroConfig = await findAstroConfig(serviceDir);
|
|
7413
7464
|
if (astroConfig) {
|
|
7414
|
-
return planAstro(serviceDir, pkg, manifestPath, project);
|
|
7465
|
+
return () => planAstro(serviceDir, pkg, manifestPath, project);
|
|
7466
|
+
}
|
|
7467
|
+
}
|
|
7468
|
+
return null;
|
|
7469
|
+
}
|
|
7470
|
+
async function plan(serviceDir, opts) {
|
|
7471
|
+
const pkg = await readPackageJson(serviceDir);
|
|
7472
|
+
const manifestPath = import_node_path40.default.join(serviceDir, "package.json");
|
|
7473
|
+
const project = opts?.project;
|
|
7474
|
+
const empty = {
|
|
7475
|
+
language: "javascript",
|
|
7476
|
+
serviceDir,
|
|
7477
|
+
dependencyEdits: [],
|
|
7478
|
+
entrypointEdits: [],
|
|
7479
|
+
envEdits: [],
|
|
7480
|
+
generatedFiles: []
|
|
7481
|
+
};
|
|
7482
|
+
if (!pkg) return empty;
|
|
7483
|
+
const frameworkDispatch = await findFrameworkDispatch(
|
|
7484
|
+
serviceDir,
|
|
7485
|
+
pkg,
|
|
7486
|
+
manifestPath,
|
|
7487
|
+
project
|
|
7488
|
+
);
|
|
7489
|
+
let entryFile = null;
|
|
7490
|
+
if (!frameworkDispatch) {
|
|
7491
|
+
entryFile = await resolveEntry(serviceDir, pkg);
|
|
7492
|
+
if (!entryFile) {
|
|
7493
|
+
return { ...empty, libOnly: true };
|
|
7415
7494
|
}
|
|
7416
7495
|
}
|
|
7496
|
+
if (frameworkDispatch) {
|
|
7497
|
+
return frameworkDispatch();
|
|
7498
|
+
}
|
|
7417
7499
|
const runtimeKind = await detectRuntimeKind(serviceDir, pkg);
|
|
7418
7500
|
if (runtimeKind !== "node") {
|
|
7419
7501
|
return { ...empty, runtimeKind };
|
|
7420
7502
|
}
|
|
7421
|
-
const entryFile = await resolveEntry(serviceDir, pkg);
|
|
7422
7503
|
if (!entryFile) {
|
|
7423
7504
|
return { ...empty, libOnly: true };
|
|
7424
7505
|
}
|
|
@@ -7436,6 +7517,16 @@ async function plan(serviceDir, opts) {
|
|
|
7436
7517
|
version: sdk.version
|
|
7437
7518
|
});
|
|
7438
7519
|
}
|
|
7520
|
+
const nonBundled = detectNonBundledInstrumentations(pkg);
|
|
7521
|
+
for (const inst of nonBundled) {
|
|
7522
|
+
if (inst.pkg in existingDeps) continue;
|
|
7523
|
+
dependencyEdits.push({
|
|
7524
|
+
file: manifestPath,
|
|
7525
|
+
kind: "add",
|
|
7526
|
+
name: inst.pkg,
|
|
7527
|
+
version: inst.version
|
|
7528
|
+
});
|
|
7529
|
+
}
|
|
7439
7530
|
const entrypointEdits = [];
|
|
7440
7531
|
try {
|
|
7441
7532
|
const raw = await import_node_fs25.promises.readFile(entryFile, "utf8");
|
|
@@ -7454,11 +7545,17 @@ async function plan(serviceDir, opts) {
|
|
|
7454
7545
|
}
|
|
7455
7546
|
const svcName = serviceNodeName(pkg, serviceDir);
|
|
7456
7547
|
const projectName = projectToken(pkg, serviceDir, project);
|
|
7548
|
+
const registrations = nonBundled.map((i) => i.registration);
|
|
7457
7549
|
const generatedFiles = [];
|
|
7458
7550
|
if (!await exists2(otelInitFile)) {
|
|
7459
7551
|
generatedFiles.push({
|
|
7460
7552
|
file: otelInitFile,
|
|
7461
|
-
contents: renderNodeOtelInit(
|
|
7553
|
+
contents: renderNodeOtelInit(
|
|
7554
|
+
otelInitContents(flavor),
|
|
7555
|
+
svcName,
|
|
7556
|
+
projectName,
|
|
7557
|
+
registrations
|
|
7558
|
+
),
|
|
7462
7559
|
skipIfExists: true
|
|
7463
7560
|
});
|
|
7464
7561
|
}
|
|
@@ -7993,6 +8090,7 @@ function renderPatch(sections) {
|
|
|
7993
8090
|
init_cjs_shims();
|
|
7994
8091
|
var import_node_fs27 = require("fs");
|
|
7995
8092
|
var import_node_http = __toESM(require("http"), 1);
|
|
8093
|
+
var import_node_net = __toESM(require("net"), 1);
|
|
7996
8094
|
var import_node_path42 = __toESM(require("path"), 1);
|
|
7997
8095
|
var import_node_child_process2 = require("child_process");
|
|
7998
8096
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
@@ -8159,6 +8257,28 @@ async function waitForDaemonReady(restPort, timeoutMs) {
|
|
|
8159
8257
|
stillBootstrapping: projects.filter((p) => p.status === "bootstrapping").map((p) => p.name)
|
|
8160
8258
|
};
|
|
8161
8259
|
}
|
|
8260
|
+
var NEAT_PORTS = [8080, 4318, 6328];
|
|
8261
|
+
async function isPortFree(port) {
|
|
8262
|
+
return new Promise((resolve) => {
|
|
8263
|
+
const server = import_node_net.default.createServer();
|
|
8264
|
+
server.once("error", () => resolve(false));
|
|
8265
|
+
server.once("listening", () => server.close(() => resolve(true)));
|
|
8266
|
+
server.listen(port, "127.0.0.1");
|
|
8267
|
+
});
|
|
8268
|
+
}
|
|
8269
|
+
async function probePortsFree() {
|
|
8270
|
+
for (const port of NEAT_PORTS) {
|
|
8271
|
+
if (!await isPortFree(port)) return { free: false, held: port };
|
|
8272
|
+
}
|
|
8273
|
+
return { free: true };
|
|
8274
|
+
}
|
|
8275
|
+
function formatPortCollisionMessage(port) {
|
|
8276
|
+
return [
|
|
8277
|
+
`neat: port ${port} is in use; the NEAT daemon needs it.`,
|
|
8278
|
+
` run \`neatd stop\` to release the previous daemon, or`,
|
|
8279
|
+
` \`lsof -i :${port}\` to find the holding process.`
|
|
8280
|
+
];
|
|
8281
|
+
}
|
|
8162
8282
|
function spawnDaemonDetached() {
|
|
8163
8283
|
const here = import_node_path42.default.dirname(new URL(importMetaUrl).pathname);
|
|
8164
8284
|
const candidates = [
|
|
@@ -8295,6 +8415,14 @@ async function runOrchestrator(opts) {
|
|
|
8295
8415
|
if (await checkDaemonHealth(restPort)) {
|
|
8296
8416
|
result.steps.daemon = "already-running";
|
|
8297
8417
|
} else {
|
|
8418
|
+
const probe = await probePortsFree();
|
|
8419
|
+
if (!probe.free) {
|
|
8420
|
+
for (const line of formatPortCollisionMessage(probe.held)) {
|
|
8421
|
+
console.error(line);
|
|
8422
|
+
}
|
|
8423
|
+
result.exitCode = 3;
|
|
8424
|
+
return result;
|
|
8425
|
+
}
|
|
8298
8426
|
try {
|
|
8299
8427
|
spawnDaemonDetached();
|
|
8300
8428
|
} catch (err) {
|
|
@@ -9102,7 +9230,8 @@ function usage() {
|
|
|
9102
9230
|
console.log(" 0 success");
|
|
9103
9231
|
console.log(" 1 server error (4xx/5xx body printed to stderr)");
|
|
9104
9232
|
console.log(" 2 misuse (missing args, bad flags) \u2014 handled before any network call");
|
|
9105
|
-
console.log(" 3 daemon
|
|
9233
|
+
console.log(" 3 environmental \u2014 daemon unreachable, or one of ports 8080 / 4318 / 6328");
|
|
9234
|
+
console.log(" is held by another process when `neat <path>` tries to spawn the daemon");
|
|
9106
9235
|
console.log("");
|
|
9107
9236
|
console.log("environment:");
|
|
9108
9237
|
console.log(" NEAT_API_URL base URL for the core REST API (default http://localhost:8080)");
|