@glasstrace/sdk 0.16.0 → 0.17.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.
@@ -8,8 +8,8 @@ import {
8
8
  } from "../chunk-CTJI2YKA.js";
9
9
  import {
10
10
  readAnonKey
11
- } from "../chunk-TM5NKZTO.js";
12
- import "../chunk-7JBKXSBU.js";
11
+ } from "../chunk-J5BW7V2D.js";
12
+ import "../chunk-GSGX76Q5.js";
13
13
  import {
14
14
  scaffoldMcpMarker
15
15
  } from "../chunk-O63DJKIJ.js";
package/dist/index.cjs CHANGED
@@ -14650,6 +14650,7 @@ var init_dist = __esm({
14650
14650
  SOURCE_MAPPED: "glasstrace.source.mapped",
14651
14651
  TRPC_PROCEDURE: "glasstrace.trpc.procedure",
14652
14652
  ERROR_RESPONSE_BODY: "glasstrace.error.response_body",
14653
+ NEXT_ACTION_DETECTED: "glasstrace.next.action.detected",
14653
14654
  // Client-side attributes
14654
14655
  PLATFORM: "glasstrace.platform",
14655
14656
  GESTURE_TYPE: "glasstrace.gesture.type",
@@ -16288,12 +16289,32 @@ function maybeShowMcpNudge(errorSummary) {
16288
16289
  `
16289
16290
  );
16290
16291
  }
16291
- var hasFired;
16292
+ function maybeShowServerActionNudge() {
16293
+ if (hasFiredServerAction) {
16294
+ return;
16295
+ }
16296
+ if (process.env.GLASSTRACE_SUPPRESS_ACTION_NUDGE === "1") {
16297
+ hasFiredServerAction = true;
16298
+ return;
16299
+ }
16300
+ const config2 = resolveConfig();
16301
+ if (isProductionDisabled(config2)) {
16302
+ hasFiredServerAction = true;
16303
+ return;
16304
+ }
16305
+ hasFiredServerAction = true;
16306
+ process.stderr.write(
16307
+ `[glasstrace] Detected a Next.js Server Action trace. Install the Glasstrace browser extension to capture the Server Action identifier for precise action-level debugging. https://glasstrace.dev/ext
16308
+ `
16309
+ );
16310
+ }
16311
+ var hasFired, hasFiredServerAction;
16292
16312
  var init_error_nudge = __esm({
16293
16313
  "src/nudge/error-nudge.ts"() {
16294
16314
  "use strict";
16295
16315
  init_env_detection();
16296
16316
  hasFired = false;
16317
+ hasFiredServerAction = false;
16297
16318
  }
16298
16319
  });
16299
16320
 
@@ -16715,6 +16736,7 @@ __export(src_exports, {
16715
16736
  SdkError: () => SdkError,
16716
16737
  SessionManager: () => SessionManager,
16717
16738
  buildImportGraph: () => buildImportGraph,
16739
+ captureCorrelationId: () => captureCorrelationId,
16718
16740
  captureError: () => captureError,
16719
16741
  classifyFetchTarget: () => classifyFetchTarget,
16720
16742
  collectSourceMaps: () => collectSourceMaps,
@@ -17620,6 +17642,7 @@ var GlasstraceSpanProcessor = class {
17620
17642
  init_esm();
17621
17643
  init_dist();
17622
17644
  init_console_capture();
17645
+ init_error_nudge();
17623
17646
  var ATTR = GLASSTRACE_ATTRIBUTE_NAMES;
17624
17647
  var API_KEY_PENDING = "pending";
17625
17648
  var MAX_PENDING_SPANS = 1024;
@@ -17738,7 +17761,8 @@ var GlasstraceExporter = class {
17738
17761
  if (typeof existingCid === "string") {
17739
17762
  extra[ATTR.CORRELATION_ID] = existingCid;
17740
17763
  }
17741
- const route = attrs["http.route"] ?? name;
17764
+ const rawRoute = attrs["http.route"];
17765
+ const route = typeof rawRoute === "string" ? rawRoute : name;
17742
17766
  if (route) {
17743
17767
  extra[ATTR.ROUTE] = route;
17744
17768
  }
@@ -17762,6 +17786,17 @@ var GlasstraceExporter = class {
17762
17786
  if (method) {
17763
17787
  extra[ATTR.HTTP_METHOD] = method;
17764
17788
  }
17789
+ const actionRoute = extractLeadingPath(route);
17790
+ if (method === "POST" && actionRoute) {
17791
+ const isApiRoute = actionRoute === "/api" || actionRoute.startsWith("/api/");
17792
+ const isInternalRoute = actionRoute.startsWith("/_next/");
17793
+ if (!isApiRoute && !isInternalRoute) {
17794
+ extra[ATTR.NEXT_ACTION_DETECTED] = true;
17795
+ if (typeof extra[ATTR.CORRELATION_ID] !== "string") {
17796
+ maybeShowServerActionNudge();
17797
+ }
17798
+ }
17799
+ }
17765
17800
  const statusCode = attrs["http.status_code"] ?? attrs["http.response.status_code"];
17766
17801
  if (statusCode !== void 0) {
17767
17802
  extra[ATTR.HTTP_STATUS_CODE] = statusCode;
@@ -17970,6 +18005,21 @@ function getExceptionEventDetails(span) {
17970
18005
  message: typeof message === "string" ? message : void 0
17971
18006
  };
17972
18007
  }
18008
+ function extractLeadingPath(raw) {
18009
+ if (!raw) return void 0;
18010
+ const trimmed = raw.trim();
18011
+ if (trimmed.length === 0) return void 0;
18012
+ if (trimmed.startsWith("/")) {
18013
+ const firstSpace = trimmed.indexOf(" ");
18014
+ return firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);
18015
+ }
18016
+ for (const token of trimmed.split(/\s+/)) {
18017
+ if (token.startsWith("/")) {
18018
+ return token;
18019
+ }
18020
+ }
18021
+ return void 0;
18022
+ }
17973
18023
  function deriveOrmProvider(instrumentationName) {
17974
18024
  const lower = instrumentationName.toLowerCase();
17975
18025
  if (lower.includes("prisma")) {
@@ -21631,7 +21681,7 @@ function registerGlasstrace(options) {
21631
21681
  setCoreState(CoreState.REGISTERING);
21632
21682
  startRuntimeStateWriter({
21633
21683
  projectRoot: process.cwd(),
21634
- sdkVersion: "0.16.0"
21684
+ sdkVersion: "0.17.0"
21635
21685
  });
21636
21686
  const config2 = resolveConfig(options);
21637
21687
  if (config2.verbose) {
@@ -21796,8 +21846,8 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
21796
21846
  if (config2.verbose) {
21797
21847
  console.info("[glasstrace] Background init firing.");
21798
21848
  }
21799
- const healthReport = collectHealthReport("0.16.0");
21800
- const initResult = await performInit(config2, anonKeyForInit, "0.16.0", healthReport);
21849
+ const healthReport = collectHealthReport("0.17.0");
21850
+ const initResult = await performInit(config2, anonKeyForInit, "0.17.0", healthReport);
21801
21851
  if (generation !== registrationGeneration) return;
21802
21852
  const currentState = getCoreState();
21803
21853
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -21820,7 +21870,7 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
21820
21870
  }
21821
21871
  maybeInstallConsoleCapture();
21822
21872
  if (didLastInitSucceed()) {
21823
- startHeartbeat(config2, anonKeyForInit, "0.16.0", generation, (newApiKey, accountId) => {
21873
+ startHeartbeat(config2, anonKeyForInit, "0.17.0", generation, (newApiKey, accountId) => {
21824
21874
  setAuthState(AuthState.CLAIMING);
21825
21875
  emitLifecycleEvent("auth:claim_started", { accountId });
21826
21876
  setResolvedApiKey(newApiKey);
@@ -22001,6 +22051,69 @@ function captureError(error48) {
22001
22051
  }
22002
22052
  }
22003
22053
 
22054
+ // src/correlation-id.ts
22055
+ init_esm();
22056
+ init_dist();
22057
+ var ATTR2 = GLASSTRACE_ATTRIBUTE_NAMES;
22058
+ var HEADER_NAME = "x-gt-cid";
22059
+ var MAX_CID_LENGTH = 128;
22060
+ function captureCorrelationId(req) {
22061
+ try {
22062
+ if (!req || !req.headers) {
22063
+ return;
22064
+ }
22065
+ const value = readHeader(req.headers);
22066
+ if (!value) {
22067
+ return;
22068
+ }
22069
+ const span = trace.getActiveSpan();
22070
+ if (!span) {
22071
+ return;
22072
+ }
22073
+ span.setAttribute(ATTR2.CORRELATION_ID, value);
22074
+ } catch {
22075
+ }
22076
+ }
22077
+ function readHeader(headers) {
22078
+ const asFetch = headers;
22079
+ if (typeof asFetch.get === "function") {
22080
+ const raw = asFetch.get(HEADER_NAME);
22081
+ return firstToken(raw);
22082
+ }
22083
+ const dict = headers;
22084
+ const direct = dict[HEADER_NAME];
22085
+ if (direct !== void 0) {
22086
+ return firstValue(direct);
22087
+ }
22088
+ for (const key of Object.keys(dict)) {
22089
+ if (key.toLowerCase() === HEADER_NAME) {
22090
+ return firstValue(dict[key]);
22091
+ }
22092
+ }
22093
+ return void 0;
22094
+ }
22095
+ function firstValue(value) {
22096
+ if (Array.isArray(value)) {
22097
+ for (const entry of value) {
22098
+ const token = firstToken(entry);
22099
+ if (token) return token;
22100
+ }
22101
+ return void 0;
22102
+ }
22103
+ return firstToken(value);
22104
+ }
22105
+ function firstToken(value) {
22106
+ if (typeof value !== "string") return void 0;
22107
+ const parts = value.split(",");
22108
+ for (const part of parts) {
22109
+ const trimmed = part.trim();
22110
+ if (trimmed.length === 0) continue;
22111
+ if (trimmed.length > MAX_CID_LENGTH) return void 0;
22112
+ return trimmed;
22113
+ }
22114
+ return void 0;
22115
+ }
22116
+
22004
22117
  // src/import-graph.ts
22005
22118
  var fs3 = __toESM(require("node:fs/promises"), 1);
22006
22119
  var fsSync = __toESM(require("node:fs"), 1);
@@ -22177,6 +22290,7 @@ async function buildImportGraph(projectRoot) {
22177
22290
  SdkError,
22178
22291
  SessionManager,
22179
22292
  buildImportGraph,
22293
+ captureCorrelationId,
22180
22294
  captureError,
22181
22295
  classifyFetchTarget,
22182
22296
  collectSourceMaps,