@neat.is/core 0.5.4-dev.20260721 → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseOtlpRequest
3
- } from "./chunk-I4NZ7PSN.js";
3
+ } from "./chunk-BZ3AJVAC.js";
4
4
 
5
5
  // src/otel-grpc.ts
6
6
  import { fileURLToPath } from "url";
@@ -138,4 +138,4 @@ export {
138
138
  reshapeGrpcRequest,
139
139
  startOtelGrpcReceiver
140
140
  };
141
- //# sourceMappingURL=chunk-4RU3AAOI.js.map
141
+ //# sourceMappingURL=chunk-MVINCLQM.js.map
package/dist/cli.cjs CHANGED
@@ -342,6 +342,11 @@ function pickEnv(spanAttrs, resourceAttrs) {
342
342
  }
343
343
  return ENV_FALLBACK;
344
344
  }
345
+ function normalizeDbSystem(attrs) {
346
+ const raw = attrs["db.system"];
347
+ if (typeof raw !== "string") return void 0;
348
+ return raw === "mongoose" ? "mongodb" : raw;
349
+ }
345
350
  function messagingDestinationOf(attrs) {
346
351
  for (const key of ["messaging.destination.name", "messaging.destination"]) {
347
352
  const v = attrs[key];
@@ -396,7 +401,7 @@ function parseOtlpRequest(body) {
396
401
  durationNanos: durationNanos(span.startTimeUnixNano, span.endTimeUnixNano),
397
402
  env: pickEnv(attrs, resourceAttrs),
398
403
  attributes: attrs,
399
- dbSystem: typeof attrs["db.system"] === "string" ? attrs["db.system"] : void 0,
404
+ dbSystem: normalizeDbSystem(attrs),
400
405
  dbName: typeof attrs["db.name"] === "string" ? attrs["db.name"] : void 0,
401
406
  dbCollection: typeof attrs["db.collection.name"] === "string" ? attrs["db.collection.name"] : typeof attrs["db.mongodb.collection"] === "string" ? attrs["db.mongodb.collection"] : void 0,
402
407
  messagingSystem: typeof attrs["messaging.system"] === "string" ? attrs["messaging.system"] : void 0,
@@ -10242,6 +10247,42 @@ function registerRoutes(scope, ctx) {
10242
10247
  return reply.code(500).send({ error: err.message });
10243
10248
  }
10244
10249
  });
10250
+ scope.get("/instrumentation", async (req, reply) => {
10251
+ const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
10252
+ if (!proj) return;
10253
+ if (!proj.scanPath) {
10254
+ return { engaged: null };
10255
+ }
10256
+ try {
10257
+ const state = await describeProjectInstrumentation({ project: proj.name, scanPath: proj.scanPath });
10258
+ const uninstrumented = await listUninstrumented({ project: proj.name, scanPath: proj.scanPath });
10259
+ if (state.hookFiles.length === 0) {
10260
+ return {
10261
+ engaged: false,
10262
+ diagnosis: {
10263
+ reason: "No instrumented entry point found \u2014 NEAT hasn't written an OTel init hook for this project.",
10264
+ fixCommand: "neat init",
10265
+ detail: "Run `neat init` so NEAT writes the instrumentation hook next to your entry point, then run your app."
10266
+ }
10267
+ };
10268
+ }
10269
+ if (uninstrumented.length > 0) {
10270
+ const names = uninstrumented.map((u) => u.library);
10271
+ const more = names.length > 1 ? ` (and ${names.length - 1} more)` : "";
10272
+ return {
10273
+ engaged: false,
10274
+ diagnosis: {
10275
+ reason: `\`${names[0]}\`${more} isn't in the auto-instrumentation set, so spans from it won't reach the graph.`,
10276
+ fixCommand: "neat extend",
10277
+ detail: `Uninstrumented on your hot path: ${names.join(", ")}. Run \`neat extend\` to wire the missing instrumentation.`
10278
+ }
10279
+ };
10280
+ }
10281
+ return { engaged: true };
10282
+ } catch {
10283
+ return { engaged: null };
10284
+ }
10285
+ });
10245
10286
  scope.post("/extend/apply", async (req, reply) => {
10246
10287
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
10247
10288
  if (!proj) return;
@@ -11997,15 +12038,21 @@ var PROVIDER_DISPATCH = {
11997
12038
  resolveTarget: createCloudflareResolveTarget(config, graph)
11998
12039
  };
11999
12040
  },
12000
- // GET /user/tokens/verify — Cloudflare's own purpose-built "is this API
12001
- // token live" endpoint. 200 on a valid token, 401 on an invalid one.
12041
+ // GET /accounts/{accountId}/tokens/verify — the *account-scoped* token-verify
12042
+ // endpoint. A Workers connector token is scoped to the account, and the
12043
+ // user-level `GET /user/tokens/verify` returns 401 "Invalid API Token" for
12044
+ // such a token even though it authenticates fine against the account's own
12045
+ // resources (confirmed live). Probing the account-scoped verify endpoint —
12046
+ // `accountId` is already required for this provider — returns 200
12047
+ // `{status:"active"}` for a working token and 401 for a bad one, so a valid
12048
+ // Workers token is no longer falsely rejected at `neat connector add`.
12002
12049
  validate({ credentials, options, fetchImpl }) {
12003
12050
  const cfg = options;
12004
12051
  const baseUrl = cfg.baseUrl ?? CLOUDFLARE_API_BASE_URL;
12005
12052
  return authProbe({
12006
12053
  provider: "cloudflare",
12007
12054
  accountKey: cfg.accountId ?? "validate",
12008
- url: `${baseUrl}/user/tokens/verify`,
12055
+ url: `${baseUrl}/accounts/${cfg.accountId ?? ""}/tokens/verify`,
12009
12056
  token: String(credentials.apiToken ?? ""),
12010
12057
  ...fetchImpl ? { fetchImpl } : {}
12011
12058
  });
@@ -13537,9 +13584,12 @@ ${OTEL_ENDPOINT_RESOLVER_ESM}
13537
13584
  ${OTEL_OTLP_PROTOCOL_JS}
13538
13585
  ${OTEL_OTLP_HEADERS_JS}
13539
13586
 
13540
- import { NodeSDK } from '@opentelemetry/sdk-node'
13541
- import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
13542
- import { trace, context } from '@opentelemetry/api'
13587
+ // Keep dependency loading inside the guard. Static ESM imports are evaluated
13588
+ // before any try/catch and would crash the host app when an install failed.
13589
+ try {
13590
+ const { NodeSDK } = await import('@opentelemetry/sdk-node')
13591
+ const { getNodeAutoInstrumentations } = await import('@opentelemetry/auto-instrumentations-node')
13592
+ const { trace, context } = await import('@opentelemetry/api')
13543
13593
 
13544
13594
  ${CALLSITE_PROCESSOR_JS}
13545
13595
 
@@ -13548,6 +13598,14 @@ __INSTRUMENTATION_BLOCK__
13548
13598
  const sdk = new NodeSDK({ instrumentations })
13549
13599
  sdk.start()
13550
13600
  ${neatWireCaptureSource(false)}
13601
+ } catch (__neatOtelErr) {
13602
+ const __neatMsg = String((__neatOtelErr && __neatOtelErr.message) || __neatOtelErr)
13603
+ if (/Cannot find (?:module|package)|MODULE_NOT_FOUND|ERR_MODULE_NOT_FOUND/.test(__neatMsg)) {
13604
+ console.warn('[neat] OpenTelemetry is not active: its packages are not installed, so this app is running without OBSERVED tracing. Run your package manager install and restart to enable it.')
13605
+ } else {
13606
+ console.warn('[neat] OpenTelemetry failed to start; the app is running without OBSERVED tracing: ' + __neatMsg)
13607
+ }
13608
+ }
13551
13609
  `;
13552
13610
  var OTEL_INIT_TS = `${OTEL_INIT_HEADER}
13553
13611
  ${OTEL_INIT_STAMP}
@@ -13562,9 +13620,12 @@ ${OTEL_ENDPOINT_RESOLVER_ESM}
13562
13620
  ${OTEL_OTLP_PROTOCOL_JS}
13563
13621
  ${OTEL_OTLP_HEADERS_JS}
13564
13622
 
13565
- import { NodeSDK } from '@opentelemetry/sdk-node'
13566
- import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
13567
- import { trace, context } from '@opentelemetry/api'
13623
+ // Top-level await preserves the static import's ordering: the host entry does
13624
+ // not run until instrumentation has started (or safely degraded).
13625
+ try {
13626
+ const { NodeSDK } = await import('@opentelemetry/sdk-node')
13627
+ const { getNodeAutoInstrumentations } = await import('@opentelemetry/auto-instrumentations-node')
13628
+ const { trace, context } = await import('@opentelemetry/api')
13568
13629
 
13569
13630
  ${CALLSITE_PROCESSOR_TS}
13570
13631
 
@@ -13573,6 +13634,14 @@ __INSTRUMENTATION_BLOCK__
13573
13634
  const sdk = new NodeSDK({ instrumentations })
13574
13635
  sdk.start()
13575
13636
  ${neatWireCaptureSource(true)}
13637
+ } catch (__neatOtelErr) {
13638
+ const __neatMsg = String((__neatOtelErr && __neatOtelErr.message) || __neatOtelErr)
13639
+ if (/Cannot find (?:module|package)|MODULE_NOT_FOUND|ERR_MODULE_NOT_FOUND/.test(__neatMsg)) {
13640
+ console.warn('[neat] OpenTelemetry is not active: its packages are not installed, so this app is running without OBSERVED tracing. Run your package manager install and restart to enable it.')
13641
+ } else {
13642
+ console.warn('[neat] OpenTelemetry failed to start; the app is running without OBSERVED tracing: ' + __neatMsg)
13643
+ }
13644
+ }
13576
13645
  `;
13577
13646
  function renderNodeOtelInit(template, serviceName, projectName, registrations = []) {
13578
13647
  const block = registrations.length === 0 ? "" : `
@@ -15871,9 +15940,26 @@ function printSummary(result, graph, dashboardUrl, daemonLog) {
15871
15940
  } else {
15872
15941
  console.log("running locally \u2014 open the dashboard, no token needed");
15873
15942
  }
15943
+ const failedInstalls = (result.steps.apply.packageManagerInstalls ?? []).filter(
15944
+ (i) => i.exitCode !== 0
15945
+ );
15874
15946
  if (daemonLog !== null) {
15875
15947
  console.log("");
15876
15948
  console.log(`daemon running in the background (logs: ${daemonLog})`);
15949
+ }
15950
+ if (failedInstalls.length > 0) {
15951
+ if (daemonLog === null) console.log("");
15952
+ console.log(
15953
+ "instrumentation is wired into your manifests, but it is NOT yet active:"
15954
+ );
15955
+ console.log(
15956
+ "the dependency install did not complete, so the OTel SDK never landed and"
15957
+ );
15958
+ console.log("OBSERVED edges will stay empty until you finish the install. Fix it:");
15959
+ for (const i of failedInstalls) {
15960
+ console.log(` run \`${i.pm} install\` in ${i.cwd}`);
15961
+ }
15962
+ } else if (daemonLog !== null) {
15877
15963
  console.log(
15878
15964
  "next: run your app or your test suite \u2014 OBSERVED edges fill in as it executes,"
15879
15965
  );