@debugbundle/cli 1.5.3 → 1.5.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.
Files changed (2) hide show
  1. package/dist/main.cjs +211 -15
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -15405,11 +15405,16 @@ var ServiceSchema = external_exports.object({
15405
15405
  environment: external_exports.string().min(1)
15406
15406
  });
15407
15407
  var CorrelationSchema = external_exports.object({
15408
- request_id: external_exports.string().nullable(),
15409
- trace_id: external_exports.string().nullable(),
15410
- session_id: external_exports.string().nullable(),
15411
- user_id_hash: external_exports.string().nullable()
15412
- }).strict();
15408
+ request_id: external_exports.string().nullable().optional(),
15409
+ trace_id: external_exports.string().nullable().optional(),
15410
+ session_id: external_exports.string().nullable().optional(),
15411
+ user_id_hash: external_exports.string().nullable().optional()
15412
+ }).strict().transform((value) => ({
15413
+ request_id: value.request_id ?? null,
15414
+ trace_id: value.trace_id ?? null,
15415
+ session_id: value.session_id ?? null,
15416
+ user_id_hash: value.user_id_hash ?? null
15417
+ }));
15413
15418
  var InlineProbeDataItemSchema = external_exports.object({
15414
15419
  label: external_exports.string().min(1),
15415
15420
  data: external_exports.record(external_exports.string(), external_exports.unknown()),
@@ -15589,7 +15594,8 @@ var EnvelopeBaseSchema = external_exports.object({
15589
15594
  sdk_version: external_exports.string().min(1),
15590
15595
  service: ServiceSchema,
15591
15596
  occurred_at: external_exports.string().datetime(),
15592
- correlation: CorrelationSchema.optional()
15597
+ correlation: CorrelationSchema.optional(),
15598
+ context: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
15593
15599
  }).strict();
15594
15600
  var EventEnvelopeSchema = external_exports.discriminatedUnion("event_type", [
15595
15601
  EnvelopeBaseSchema.extend({ event_type: external_exports.literal("backend_exception"), payload: BackendExceptionPayloadSchema }),
@@ -15618,6 +15624,7 @@ function createEventEnvelope(input2) {
15618
15624
  session_id: null,
15619
15625
  user_id_hash: null
15620
15626
  },
15627
+ context: input2.context,
15621
15628
  payload: input2.payload
15622
15629
  };
15623
15630
  return EventEnvelopeSchema.parse(candidate);
@@ -17143,6 +17150,9 @@ function createRetrievalApi(client) {
17143
17150
  if (input2.firstSeenAfter !== void 0) {
17144
17151
  query.set("first_seen_after", input2.firstSeenAfter);
17145
17152
  }
17153
+ if (input2.attentionAfter !== void 0) {
17154
+ query.set("attention_after", input2.attentionAfter);
17155
+ }
17146
17156
  if (input2.cursor !== void 0) {
17147
17157
  query.set("cursor", input2.cursor);
17148
17158
  }
@@ -17899,6 +17909,167 @@ function redact(payload, options) {
17899
17909
 
17900
17910
  // ../../packages/event-normalizer/src/index.ts
17901
17911
  var FINGERPRINT_VERSION = "v1";
17912
+ var PAYLOAD_ALLOWED_KEYS = {
17913
+ backend_exception: /* @__PURE__ */ new Set(["name", "message", "stack", "handled", "request", "response", "runtime", "probe_data"]),
17914
+ request_event: /* @__PURE__ */ new Set([
17915
+ "method",
17916
+ "path",
17917
+ "query",
17918
+ "headers",
17919
+ "body",
17920
+ "response_status",
17921
+ "duration_ms",
17922
+ "route_template",
17923
+ "response_headers",
17924
+ "response_body"
17925
+ ]),
17926
+ log_event: /* @__PURE__ */ new Set(["level", "message", "attributes"]),
17927
+ frontend_breadcrumb: /* @__PURE__ */ new Set(["breadcrumb_type", "route", "data"]),
17928
+ frontend_exception: /* @__PURE__ */ new Set([
17929
+ "name",
17930
+ "message",
17931
+ "stack",
17932
+ "route",
17933
+ "browser",
17934
+ "breadcrumbs",
17935
+ "device",
17936
+ "browser_event",
17937
+ "rejection_reason",
17938
+ "dom_context",
17939
+ "probe_data"
17940
+ ]),
17941
+ deploy_metadata: /* @__PURE__ */ new Set(["commit_sha", "version", "branch", "environment", "deployed_at"]),
17942
+ error_suppressed: /* @__PURE__ */ new Set(["fingerprint", "suppressed_count", "window_seconds", "first_seen", "last_seen"]),
17943
+ probe_event: /* @__PURE__ */ new Set(["label", "data", "activation_id", "probe_label_pattern"])
17944
+ };
17945
+ function isRecord3(candidate) {
17946
+ return typeof candidate === "object" && candidate !== null && !Array.isArray(candidate);
17947
+ }
17948
+ function cloneRecord(candidate) {
17949
+ return { ...candidate };
17950
+ }
17951
+ function readString2(candidate) {
17952
+ if (typeof candidate === "string") {
17953
+ return candidate;
17954
+ }
17955
+ if (typeof candidate === "number" || typeof candidate === "boolean") {
17956
+ return String(candidate);
17957
+ }
17958
+ return null;
17959
+ }
17960
+ function readNonNegativeNumber(candidate, fallback) {
17961
+ if (typeof candidate === "number" && Number.isFinite(candidate) && candidate >= 0) {
17962
+ return candidate;
17963
+ }
17964
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
17965
+ const parsed = Number(candidate);
17966
+ if (Number.isFinite(parsed) && parsed >= 0) {
17967
+ return parsed;
17968
+ }
17969
+ }
17970
+ return fallback;
17971
+ }
17972
+ function normalizeMap(candidate) {
17973
+ return isRecord3(candidate) ? cloneRecord(candidate) : {};
17974
+ }
17975
+ function mergeContext(baseContext, incomingContext) {
17976
+ if (!isRecord3(incomingContext)) {
17977
+ return baseContext;
17978
+ }
17979
+ return {
17980
+ ...baseContext,
17981
+ ...incomingContext
17982
+ };
17983
+ }
17984
+ function normalizeCorrelation(candidate) {
17985
+ if (!isRecord3(candidate)) {
17986
+ return void 0;
17987
+ }
17988
+ return {
17989
+ request_id: readString2(candidate["request_id"]),
17990
+ trace_id: readString2(candidate["trace_id"]),
17991
+ session_id: readString2(candidate["session_id"]),
17992
+ user_id_hash: readString2(candidate["user_id_hash"])
17993
+ };
17994
+ }
17995
+ function normalizeBackendExceptionPayload(payload) {
17996
+ const request = normalizeMap(payload["request"]);
17997
+ payload["request"] = {
17998
+ method: readString2(request["method"]) ?? "UNKNOWN",
17999
+ path: readString2(request["path"]) ?? "/",
18000
+ query: normalizeMap(request["query"]),
18001
+ headers: normalizeMap(request["headers"]),
18002
+ ..."body" in request ? { body: request["body"] ?? null } : {}
18003
+ };
18004
+ const response = normalizeMap(payload["response"]);
18005
+ payload["response"] = {
18006
+ status_code: readNonNegativeNumber(response["status_code"], 0),
18007
+ ..."headers" in response ? { headers: normalizeMap(response["headers"]) } : {},
18008
+ ..."body" in response ? { body: response["body"] } : {}
18009
+ };
18010
+ }
18011
+ function normalizeRequestEventPayload(payload) {
18012
+ payload["query"] = normalizeMap(payload["query"]);
18013
+ payload["headers"] = normalizeMap(payload["headers"]);
18014
+ payload["response_status"] = readNonNegativeNumber(payload["response_status"], 0);
18015
+ payload["duration_ms"] = readNonNegativeNumber(payload["duration_ms"], 0);
18016
+ }
18017
+ function normalizePayloadExtras(input2) {
18018
+ const allowedKeys = PAYLOAD_ALLOWED_KEYS[input2.eventType];
18019
+ if (allowedKeys === void 0) {
18020
+ return input2.context;
18021
+ }
18022
+ let context = input2.context;
18023
+ for (const key of Object.keys(input2.payload)) {
18024
+ if (allowedKeys.has(key)) {
18025
+ continue;
18026
+ }
18027
+ context = mergeContext(context, { [key]: input2.payload[key] });
18028
+ delete input2.payload[key];
18029
+ }
18030
+ return context;
18031
+ }
18032
+ function normalizeCompatibleEventCandidate(candidate) {
18033
+ if (!isRecord3(candidate)) {
18034
+ return candidate;
18035
+ }
18036
+ const event = cloneRecord(candidate);
18037
+ const eventType = typeof event["event_type"] === "string" ? event["event_type"] : "";
18038
+ let context = normalizeMap(event["context"]);
18039
+ if (typeof event["sdk_language"] === "string") {
18040
+ context = mergeContext(context, { sdk_language: event["sdk_language"] });
18041
+ delete event["sdk_language"];
18042
+ }
18043
+ const correlation = normalizeCorrelation(event["correlation"]);
18044
+ if (correlation !== void 0) {
18045
+ event["correlation"] = correlation;
18046
+ }
18047
+ if (isRecord3(event["payload"])) {
18048
+ const payload = cloneRecord(event["payload"]);
18049
+ context = mergeContext(context, payload["context"]);
18050
+ delete payload["context"];
18051
+ if (eventType === "backend_exception") {
18052
+ normalizeBackendExceptionPayload(payload);
18053
+ }
18054
+ if (eventType === "request_event") {
18055
+ const attributes = isRecord3(payload["attributes"]) ? payload["attributes"] : null;
18056
+ if (typeof payload["route_template"] !== "string" && typeof attributes?.["route_template"] === "string") {
18057
+ payload["route_template"] = attributes["route_template"];
18058
+ }
18059
+ context = mergeContext(context, attributes);
18060
+ delete payload["attributes"];
18061
+ normalizeRequestEventPayload(payload);
18062
+ }
18063
+ context = normalizePayloadExtras({ eventType, payload, context });
18064
+ event["payload"] = payload;
18065
+ }
18066
+ if (Object.keys(context).length > 0) {
18067
+ event["context"] = context;
18068
+ } else {
18069
+ delete event["context"];
18070
+ }
18071
+ return event;
18072
+ }
17902
18073
  function inferMatchedFields(event) {
17903
18074
  const matchedFields = ["environment", "normalized_message"];
17904
18075
  if (event.error_type !== null) {
@@ -18143,7 +18314,7 @@ function stableJson(value) {
18143
18314
  return `{${pairs.join(",")}}`;
18144
18315
  }
18145
18316
  function validateEvent(candidate) {
18146
- return EventEnvelopeSchema.safeParse(candidate);
18317
+ return EventEnvelopeSchema.safeParse(normalizeCompatibleEventCandidate(candidate));
18147
18318
  }
18148
18319
  function normalizeEvent(event) {
18149
18320
  const redactedPayload = redact(event.payload).redacted;
@@ -20805,9 +20976,13 @@ function parseLocalIncident(candidate) {
20805
20976
  throw createReadError(400, "invalid_local_state");
20806
20977
  }
20807
20978
  const resolvedAt = candidate["resolved_at"];
20979
+ const regressedAt = candidate["regressed_at"];
20808
20980
  if (resolvedAt !== void 0 && resolvedAt !== null && typeof resolvedAt !== "string") {
20809
20981
  throw createReadError(400, "invalid_local_state");
20810
20982
  }
20983
+ if (regressedAt !== void 0 && regressedAt !== null && typeof regressedAt !== "string") {
20984
+ throw createReadError(400, "invalid_local_state");
20985
+ }
20811
20986
  if (typeof candidate["occurrence_count"] !== "number" || typeof candidate["generation_number"] !== "number") {
20812
20987
  throw createReadError(400, "invalid_local_state");
20813
20988
  }
@@ -20842,6 +21017,7 @@ function parseLocalIncident(candidate) {
20842
21017
  severity: candidate["severity"],
20843
21018
  status: candidate["status"],
20844
21019
  ...resolvedAt === void 0 ? {} : { resolved_at: resolvedAt },
21020
+ ...regressedAt === void 0 ? {} : { regressed_at: regressedAt },
20845
21021
  first_seen_at: candidate["first_seen_at"],
20846
21022
  last_seen_at: candidate["last_seen_at"],
20847
21023
  occurrence_count: candidate["occurrence_count"],
@@ -20947,7 +21123,12 @@ async function listLocalIncidents(input2, dependencies) {
20947
21123
  return incident.status === "open";
20948
21124
  }
20949
21125
  return incident.status === input2.status;
20950
- }).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).filter((incident) => input2.firstSeenAfter === void 0 ? true : incident.first_seen_at >= input2.firstSeenAfter).sort(sortIncidentsDescending);
21126
+ }).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).filter((incident) => input2.firstSeenAfter === void 0 ? true : incident.first_seen_at >= input2.firstSeenAfter).filter((incident) => {
21127
+ if (input2.attentionAfter === void 0) {
21128
+ return true;
21129
+ }
21130
+ return incident.first_seen_at >= input2.attentionAfter || incident.regressed_at != null && incident.regressed_at >= input2.attentionAfter;
21131
+ }).sort(sortIncidentsDescending);
20951
21132
  const startIndex = input2.cursor === void 0 ? 0 : incidents.findIndex((incident) => buildCursor(incident) === input2.cursor) + 1;
20952
21133
  const pagedIncidents = input2.limit === void 0 ? incidents.slice(startIndex) : incidents.slice(startIndex, startIndex + input2.limit);
20953
21134
  const hasMore = input2.limit !== void 0 && startIndex + input2.limit < incidents.length;
@@ -26913,7 +27094,7 @@ var ProfileSchema2 = external_exports.object({
26913
27094
  framework: external_exports.string().min(1)
26914
27095
  }))
26915
27096
  });
26916
- function isRecord3(value) {
27097
+ function isRecord4(value) {
26917
27098
  return typeof value === "object" && value !== null;
26918
27099
  }
26919
27100
  function slugify2(value) {
@@ -27003,7 +27184,7 @@ async function ingestCommand(input2, dependencies = {}) {
27003
27184
  })
27004
27185
  };
27005
27186
  } catch (error) {
27006
- const message = isRecord3(error) && typeof error["message"] === "string" ? error["message"] : "Failed to ingest log file.";
27187
+ const message = isRecord4(error) && typeof error["message"] === "string" ? error["message"] : "Failed to ingest log file.";
27007
27188
  return {
27008
27189
  exitCode: 1,
27009
27190
  output: message
@@ -28553,6 +28734,7 @@ async function listAllCloudIncidents(input2, api) {
28553
28734
  ...input2.status === void 0 ? {} : { status: input2.status },
28554
28735
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28555
28736
  ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
28737
+ ...input2.attentionAfter === void 0 ? {} : { attentionAfter: input2.attentionAfter },
28556
28738
  ...cursor === void 0 ? {} : { cursor }
28557
28739
  });
28558
28740
  incidents.push(
@@ -28574,7 +28756,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
28574
28756
  ...input2.service === void 0 ? {} : { service: input2.service },
28575
28757
  ...input2.status === void 0 ? {} : { status: input2.status },
28576
28758
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28577
- ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
28759
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
28760
+ ...input2.attentionAfter === void 0 ? {} : { attentionAfter: input2.attentionAfter }
28578
28761
  },
28579
28762
  dependencies
28580
28763
  );
@@ -28586,7 +28769,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
28586
28769
  ...input2.service === void 0 ? {} : { service: input2.service },
28587
28770
  ...input2.status === void 0 ? {} : { status: input2.status },
28588
28771
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28589
- ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
28772
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
28773
+ ...input2.attentionAfter === void 0 ? {} : { attentionAfter: input2.attentionAfter }
28590
28774
  },
28591
28775
  api
28592
28776
  );
@@ -28635,6 +28819,9 @@ async function listIncidentsCommand(input2, api) {
28635
28819
  if (input2.firstSeenAfter !== void 0) {
28636
28820
  requestInput.firstSeenAfter = input2.firstSeenAfter;
28637
28821
  }
28822
+ if (input2.attentionAfter !== void 0) {
28823
+ requestInput.attentionAfter = input2.attentionAfter;
28824
+ }
28638
28825
  if (input2.cursor !== void 0) {
28639
28826
  requestInput.cursor = input2.cursor;
28640
28827
  }
@@ -28668,6 +28855,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
28668
28855
  ...statusFilter === void 0 ? {} : { status: statusFilter },
28669
28856
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28670
28857
  ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
28858
+ ...input2.attentionAfter === void 0 ? {} : { attentionAfter: input2.attentionAfter },
28671
28859
  ...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
28672
28860
  ...input2.limit === void 0 ? {} : { limit: input2.limit }
28673
28861
  },
@@ -28693,6 +28881,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
28693
28881
  ...statusFilter === void 0 ? {} : { status: statusFilter },
28694
28882
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28695
28883
  ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
28884
+ ...input2.attentionAfter === void 0 ? {} : { attentionAfter: input2.attentionAfter },
28696
28885
  ...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
28697
28886
  ...input2.limit === void 0 ? {} : { limit: input2.limit },
28698
28887
  ...input2.json === void 0 ? {} : { json: input2.json }
@@ -28731,6 +28920,9 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
28731
28920
  if (input2.firstSeenAfter !== void 0) {
28732
28921
  commandInput.firstSeenAfter = input2.firstSeenAfter;
28733
28922
  }
28923
+ if (input2.attentionAfter !== void 0) {
28924
+ commandInput.attentionAfter = input2.attentionAfter;
28925
+ }
28734
28926
  if (input2.cursor !== void 0) {
28735
28927
  commandInput.cursor = input2.cursor;
28736
28928
  }
@@ -30455,7 +30647,7 @@ var CLI_USAGE_LINES = [
30455
30647
  " debugbundle login --github-device [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
30456
30648
  " debugbundle profile validate [--json]",
30457
30649
  " debugbundle whoami [--auth-file <path>] [--json]",
30458
- " debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <active|open|resolved|regressed|all>] [--severity <severity>] [--first-seen-after <ISO8601>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
30650
+ " debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <active|open|resolved|regressed|all>] [--severity <severity>] [--first-seen-after <ISO8601>] [--attention-after <ISO8601>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
30459
30651
  " debugbundle inspect <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
30460
30652
  " debugbundle explain <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
30461
30653
  " debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--auth-file <path>] [--json]",
@@ -36950,7 +37142,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
36950
37142
  // package.json
36951
37143
  var package_default = {
36952
37144
  name: "@debugbundle/cli",
36953
- version: "1.5.3",
37145
+ version: "1.5.4",
36954
37146
  private: false,
36955
37147
  description: "Command-line interface for DebugBundle",
36956
37148
  license: "AGPL-3.0-only",
@@ -37241,7 +37433,7 @@ ${formatUsage()}`
37241
37433
  return await (dependencies.whoamiCommand ?? whoamiCommand)(appendCommonAuthOptions(parsedArgv, {}));
37242
37434
  }
37243
37435
  if (command === "incidents") {
37244
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "first-seen-after", "cursor", "limit"]);
37436
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "first-seen-after", "attention-after", "cursor", "limit"]);
37245
37437
  ensureNoExtraPositionals(parsedArgv, 1);
37246
37438
  const input2 = appendCommonAuthOptions(parsedArgv, {});
37247
37439
  const source = readRetrievalSource(parsedArgv);
@@ -37272,6 +37464,10 @@ ${formatUsage()}`
37272
37464
  if (firstSeenAfter !== void 0) {
37273
37465
  input2.firstSeenAfter = firstSeenAfter;
37274
37466
  }
37467
+ const attentionAfter = readStringOption(parsedArgv, "attention-after");
37468
+ if (attentionAfter !== void 0) {
37469
+ input2.attentionAfter = attentionAfter;
37470
+ }
37275
37471
  const cursor = readStringOption(parsedArgv, "cursor");
37276
37472
  if (cursor !== void 0) {
37277
37473
  input2.cursor = cursor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugbundle/cli",
3
- "version": "1.5.3",
3
+ "version": "1.5.4",
4
4
  "private": false,
5
5
  "description": "Command-line interface for DebugBundle",
6
6
  "license": "AGPL-3.0-only",