@debugbundle/cli 0.1.5 → 0.1.7

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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/main.cjs +208 -111
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -21,6 +21,7 @@ debugbundle setup --non-interactive
21
21
  debugbundle doctor --privacy
22
22
  debugbundle verify local
23
23
  debugbundle verify cloud --project-id <id> --trigger-5xx
24
+ debugbundle verify cloud --project-id <id> --trigger-4xx 403
24
25
  debugbundle process
25
26
  debugbundle incidents
26
27
  debugbundle explain <incident-id> --source cloud
package/dist/main.cjs CHANGED
@@ -16740,6 +16740,16 @@ var STORAGE_SCHEMA_MIGRATIONS = [
16740
16740
  statements: [
16741
16741
  "ALTER TABLE capture_policies ADD COLUMN IF NOT EXISTS immediate_client_error_statuses jsonb"
16742
16742
  ]
16743
+ }),
16744
+ defineStorageSchemaMigration({
16745
+ id: "202605150001_add_user_avatar_columns",
16746
+ description: "Add cached user avatar metadata for GitHub and Gravatar profile images.",
16747
+ statements: [
16748
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_source text",
16749
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_object_key text",
16750
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_content_type text",
16751
+ "ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_updated_at timestamptz"
16752
+ ]
16743
16753
  })
16744
16754
  ];
16745
16755
 
@@ -17495,6 +17505,10 @@ var ProjectMetricsSchema = external_exports.object({
17495
17505
  var ProjectRecordSchema = external_exports.object({
17496
17506
  project_id: external_exports.string(),
17497
17507
  organization_id: external_exports.string(),
17508
+ owner_user_id: external_exports.string(),
17509
+ owner_email: external_exports.string().email(),
17510
+ relationship: external_exports.enum(["owned", "shared"]),
17511
+ effective_role: external_exports.enum(["owner", "admin", "member"]),
17498
17512
  name: external_exports.string(),
17499
17513
  slug: external_exports.string(),
17500
17514
  environment_default: external_exports.string(),
@@ -17512,6 +17526,10 @@ var ProjectCreateResponseSchema = external_exports.object({
17512
17526
  var DeletedProjectRecordSchema = external_exports.object({
17513
17527
  project_id: external_exports.string(),
17514
17528
  organization_id: external_exports.string(),
17529
+ owner_user_id: external_exports.string(),
17530
+ owner_email: external_exports.string().email(),
17531
+ relationship: external_exports.enum(["owned", "shared"]),
17532
+ effective_role: external_exports.enum(["owner", "admin", "member"]),
17515
17533
  name: external_exports.string(),
17516
17534
  slug: external_exports.string(),
17517
17535
  environment_default: external_exports.string(),
@@ -18490,8 +18508,7 @@ var BillingSummarySchema = external_exports.object({
18490
18508
  retained_bundle_cap: BillingUsageMetricSchema,
18491
18509
  monthly_remote_activations: BillingUsageMetricSchema,
18492
18510
  monthly_alert_deliveries: BillingUsageMetricSchema
18493
- }).strict(),
18494
- email_verification_required: external_exports.boolean().optional()
18511
+ }).strict()
18495
18512
  }).strict();
18496
18513
  var BillingSummaryResponseSchema = external_exports.object({
18497
18514
  billing: BillingSummarySchema
@@ -24590,7 +24607,7 @@ function formatResult(input, exitCode, checks, errors, incidentId) {
24590
24607
  };
24591
24608
  }
24592
24609
  function buildCloudSuggestedActions(status, incidentId, mode = "passive_recent_incident") {
24593
- if (status === "healthy" && incidentId !== void 0 && mode === "active_5xx") {
24610
+ if (status === "healthy" && incidentId !== void 0 && (mode === "active_5xx" || mode === "active_4xx")) {
24594
24611
  return [
24595
24612
  `Run debugbundle inspect ${incidentId} --source cloud to inspect why the incident fired.`,
24596
24613
  `Run debugbundle bundle ${incidentId} --source cloud to fetch the generated debug bundle.`
@@ -24660,11 +24677,11 @@ function localFailureStepName(checks) {
24660
24677
  function cloudVerificationRunId(now) {
24661
24678
  return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
24662
24679
  }
24663
- function requestFailureReason() {
24680
+ function requestFailureReason(responseStatus) {
24664
24681
  const incidentReason = deriveIncidentReasonFromSignal({
24665
24682
  event_type: "request_event",
24666
24683
  event_class: "incident_signal",
24667
- response_status: 503
24684
+ response_status: responseStatus
24668
24685
  });
24669
24686
  if (incidentReason === null) {
24670
24687
  throw new Error("request_failure_reason_unavailable");
@@ -24673,6 +24690,9 @@ function requestFailureReason() {
24673
24690
  }
24674
24691
  function buildCloudVerificationEvent(input) {
24675
24692
  const runId = cloudVerificationRunId(input.now);
24693
+ const is5xxVerification = input.responseStatus >= 500;
24694
+ const routeTemplate = is5xxVerification ? "/debugbundle/verify/cloud" : `/debugbundle/verify/cloud/client-error/${input.responseStatus}`;
24695
+ const verificationLabel = is5xxVerification ? "true" : `client-error-${input.responseStatus}`;
24676
24696
  return createEventEnvelope({
24677
24697
  event_type: "request_event",
24678
24698
  sdk_name: "debugbundle-cli",
@@ -24686,28 +24706,39 @@ function buildCloudVerificationEvent(input) {
24686
24706
  occurred_at: input.now.toISOString(),
24687
24707
  payload: {
24688
24708
  method: "GET",
24689
- path: "/debugbundle/verify/cloud",
24690
- route_template: "/debugbundle/verify/cloud",
24709
+ path: routeTemplate,
24710
+ route_template: routeTemplate,
24691
24711
  query: {
24692
24712
  debugbundle_verification: true,
24693
- run_id: runId
24713
+ run_id: runId,
24714
+ synthetic_status: input.responseStatus
24694
24715
  },
24695
24716
  headers: {
24696
- "x-debugbundle-verification": "true"
24717
+ "x-debugbundle-verification": verificationLabel
24697
24718
  },
24698
- response_status: 503,
24719
+ response_status: input.responseStatus,
24699
24720
  duration_ms: 37,
24700
24721
  response_headers: {
24701
- "x-debugbundle-verification": "true"
24722
+ "x-debugbundle-verification": verificationLabel
24702
24723
  },
24703
24724
  response_body: {
24704
- error: "debugbundle_cloud_verification",
24725
+ error: is5xxVerification ? "debugbundle_cloud_verification" : "debugbundle_cloud_client_error_verification",
24705
24726
  synthetic: true,
24706
- run_id: runId
24727
+ run_id: runId,
24728
+ response_status: input.responseStatus
24707
24729
  }
24708
24730
  }
24709
24731
  });
24710
24732
  }
24733
+ function validateActiveCloudVerificationInput(input) {
24734
+ if (input.trigger5xx === true && input.trigger4xxStatus !== void 0) {
24735
+ return "Choose either --trigger-5xx or --trigger-4xx, not both.";
24736
+ }
24737
+ if (input.trigger4xxStatus !== void 0 && (input.trigger4xxStatus < 400 || input.trigger4xxStatus > 499)) {
24738
+ return "--trigger-4xx must be an integer status between 400 and 499.";
24739
+ }
24740
+ return null;
24741
+ }
24711
24742
  async function sendEventsToApi2(input, dependencies = {}) {
24712
24743
  const fetchImpl = dependencies.fetchImpl ?? fetch;
24713
24744
  const baseUrl = input.baseUrl.endsWith("/") ? input.baseUrl.slice(0, -1) : input.baseUrl;
@@ -24899,6 +24930,15 @@ async function verifyCloudCommand(input, dependencies = {}) {
24899
24930
  const checks = [];
24900
24931
  const environment = input.environment ?? "production";
24901
24932
  const maxAgeMinutes = input.maxAgeMinutes ?? 15;
24933
+ const activeInputError = validateActiveCloudVerificationInput(input);
24934
+ if (activeInputError !== null) {
24935
+ checks.push({
24936
+ name: "trigger-input",
24937
+ status: "error",
24938
+ message: activeInputError
24939
+ });
24940
+ return formatCloudResult(input, 4, checks, [activeInputError]);
24941
+ }
24902
24942
  const readAuthState = dependencies.readAuthState ?? readCliAuthState;
24903
24943
  let authState;
24904
24944
  try {
@@ -24931,7 +24971,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
24931
24971
  requestInput,
24932
24972
  dependencies.fetchImpl === void 0 ? {} : { fetchImpl: dependencies.fetchImpl }
24933
24973
  ));
24934
- if (input.trigger5xx === true) {
24974
+ if (input.trigger5xx === true || input.trigger4xxStatus !== void 0) {
24935
24975
  const verificationStartedAt = now();
24936
24976
  const runId = cloudVerificationRunId(verificationStartedAt);
24937
24977
  const serviceName = input.service ?? `debugbundle-verify-cloud-${runId}`;
@@ -24939,16 +24979,20 @@ async function verifyCloudCommand(input, dependencies = {}) {
24939
24979
  const pollAttempts = dependencies.pollAttempts ?? 6;
24940
24980
  const pollIntervalMs = dependencies.pollIntervalMs ?? 2e3;
24941
24981
  const sleep = dependencies.sleep ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
24982
+ const responseStatus = input.trigger4xxStatus ?? 503;
24983
+ const activeMode = input.trigger4xxStatus !== void 0 ? "active_4xx" : "active_5xx";
24984
+ const activeCheckName = input.trigger4xxStatus !== void 0 ? "active-4xx-event" : "active-5xx-event";
24985
+ const statusLabel = input.trigger4xxStatus !== void 0 ? `${responseStatus}` : "5xx";
24942
24986
  const verification = {
24943
- mode: "active_5xx",
24987
+ mode: activeMode,
24944
24988
  bundle_status: "unknown",
24945
- classification_reason: requestFailureReason()
24989
+ classification_reason: requestFailureReason(responseStatus)
24946
24990
  };
24947
24991
  const errors = [];
24948
24992
  let exitCode = 0;
24949
24993
  let tokenId = null;
24950
24994
  let incidentId;
24951
- let activeStep = "active-5xx-event";
24995
+ let activeStep = activeCheckName;
24952
24996
  try {
24953
24997
  const token = await createProjectToken({
24954
24998
  bearerToken: authState.bearer_token,
@@ -24962,7 +25006,8 @@ async function verifyCloudCommand(input, dependencies = {}) {
24962
25006
  const event = buildCloudVerificationEvent({
24963
25007
  now: verificationStartedAt,
24964
25008
  serviceName,
24965
- environment
25009
+ environment,
25010
+ responseStatus
24966
25011
  });
24967
25012
  const ingestion = await sendEvents({
24968
25013
  baseUrl: authState.base_url,
@@ -24971,12 +25016,12 @@ async function verifyCloudCommand(input, dependencies = {}) {
24971
25016
  });
24972
25017
  verification.accepted_event_count = ingestion.accepted;
24973
25018
  if (ingestion.accepted < 1 || ingestion.rejected > 0 || ingestion.errors.length > 0) {
24974
- throw new Error(`Synthetic 5xx ingestion was not fully accepted: accepted=${ingestion.accepted}, rejected=${ingestion.rejected}.`);
25019
+ throw new Error(`Synthetic ${statusLabel} ingestion was not fully accepted: accepted=${ingestion.accepted}, rejected=${ingestion.rejected}.`);
24975
25020
  }
24976
25021
  checks.push({
24977
- name: "active-5xx-event",
25022
+ name: activeCheckName,
24978
25023
  status: "ok",
24979
- message: "Sent synthetic 5xx request_event through cloud ingestion."
25024
+ message: `Sent synthetic ${statusLabel} request_event through cloud ingestion.`
24980
25025
  });
24981
25026
  activeStep = "incident-retrieval";
24982
25027
  for (let attempt = 1; attempt <= pollAttempts; attempt += 1) {
@@ -24994,7 +25039,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
24994
25039
  if (candidate !== void 0) {
24995
25040
  incidentId = candidate.incident_id;
24996
25041
  verification.incident_id = candidate.incident_id;
24997
- verification.classification_reason = candidate.incident_reason ?? requestFailureReason();
25042
+ verification.classification_reason = candidate.incident_reason ?? requestFailureReason(responseStatus);
24998
25043
  break;
24999
25044
  }
25000
25045
  if (attempt < pollAttempts) {
@@ -25002,12 +25047,12 @@ async function verifyCloudCommand(input, dependencies = {}) {
25002
25047
  }
25003
25048
  }
25004
25049
  if (incidentId === void 0) {
25005
- throw new Error("Synthetic 5xx request was accepted but no matching cloud incident was visible yet.");
25050
+ throw new Error(`Synthetic ${statusLabel} request was accepted but no matching cloud incident was visible yet.`);
25006
25051
  }
25007
25052
  checks.push({
25008
25053
  name: "incident-retrieval",
25009
25054
  status: "ok",
25010
- message: `Retrieved cloud incident ${incidentId} for the synthetic 5xx request.`
25055
+ message: `Retrieved cloud incident ${incidentId} for the synthetic ${statusLabel} request.`
25011
25056
  });
25012
25057
  activeStep = "bundle-status";
25013
25058
  const bundle = await getBundle({
@@ -25273,7 +25318,7 @@ var CLI_USAGE_LINES = [
25273
25318
  " debugbundle clean [--events] [--bundles] [--all] [--older-than <Nd>] [--json]",
25274
25319
  " debugbundle validate [--fix] [--json]",
25275
25320
  " debugbundle verify local [--json]",
25276
- " debugbundle verify cloud --project-id <id> [--trigger-5xx] [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25321
+ " debugbundle verify cloud --project-id <id> [--trigger-5xx | --trigger-4xx <400-499>] [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25277
25322
  " debugbundle smoke --project-id <id> [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25278
25323
  " debugbundle login [--base-url <url>] [--auth-file <path>] [--json]",
25279
25324
  " debugbundle login <member-token> [--base-url <url>] [--auth-file <path>] [--json]",
@@ -25339,12 +25384,12 @@ var CLI_USAGE_LINES = [
25339
25384
  " debugbundle probe activate <project-id> --label-pattern <pattern> [--service <name>] [--environment <name>] [--ttl-seconds <n>] [--trigger-ttl-seconds <n>] [--auth-file <path>] [--json]",
25340
25385
  " debugbundle probe list <project-id> [--auth-file <path>] [--json]",
25341
25386
  " debugbundle probe deactivate <project-id> <activation-id> [--auth-file <path>] [--json]",
25342
- " debugbundle member list [--auth-file <path>] [--json]",
25343
- " debugbundle member invites [--auth-file <path>] [--json]",
25344
- " debugbundle member invite --email <email> --role <owner|admin|member> [--auth-file <path>] [--json]",
25345
- " debugbundle member cancel-invite <invite-id> [--auth-file <path>] [--json]",
25346
- " debugbundle member update-role <user-id> --role <owner|admin|member> [--auth-file <path>] [--json]",
25347
- " debugbundle member remove <user-id> [--auth-file <path>] [--json]"
25387
+ " debugbundle project members list --project-id <id> [--auth-file <path>] [--json]",
25388
+ " debugbundle project members invites --project-id <id> [--auth-file <path>] [--json]",
25389
+ " debugbundle project members invite --project-id <id> --email <email> --role <admin|member> [--auth-file <path>] [--json]",
25390
+ " debugbundle project members cancel-invite <invite-id> --project-id <id> [--auth-file <path>] [--json]",
25391
+ " debugbundle project members update-role <user-id> --project-id <id> --role <admin|member> [--auth-file <path>] [--json]",
25392
+ " debugbundle project members remove <user-id> --project-id <id> [--auth-file <path>] [--json]"
25348
25393
  ];
25349
25394
  function formatUsage() {
25350
25395
  return CLI_USAGE_LINES.join("\n");
@@ -27432,7 +27477,7 @@ function createMemberApi(httpClient) {
27432
27477
  async listMembers(input) {
27433
27478
  const response = await httpClient.request({
27434
27479
  method: "GET",
27435
- path: "/v1/organization/members",
27480
+ path: `/v1/projects/${input.projectId}/members`,
27436
27481
  bearerToken: input.bearerToken
27437
27482
  });
27438
27483
  if (response.status !== 200) {
@@ -27443,7 +27488,7 @@ function createMemberApi(httpClient) {
27443
27488
  async listInvites(input) {
27444
27489
  const response = await httpClient.request({
27445
27490
  method: "GET",
27446
- path: "/v1/organization/members/invites",
27491
+ path: `/v1/projects/${input.projectId}/invites`,
27447
27492
  bearerToken: input.bearerToken
27448
27493
  });
27449
27494
  if (response.status !== 200) {
@@ -27454,7 +27499,7 @@ function createMemberApi(httpClient) {
27454
27499
  async inviteMember(input) {
27455
27500
  const response = await httpClient.request({
27456
27501
  method: "POST",
27457
- path: "/v1/organization/members/invite",
27502
+ path: `/v1/projects/${input.projectId}/invite`,
27458
27503
  bearerToken: input.bearerToken,
27459
27504
  body: { email: input.email, role: input.role }
27460
27505
  });
@@ -27466,7 +27511,7 @@ function createMemberApi(httpClient) {
27466
27511
  async cancelInvite(input) {
27467
27512
  const response = await httpClient.request({
27468
27513
  method: "DELETE",
27469
- path: `/v1/organization/members/invites/${input.inviteId}`,
27514
+ path: `/v1/projects/${input.projectId}/invites/${input.inviteId}`,
27470
27515
  bearerToken: input.bearerToken
27471
27516
  });
27472
27517
  if (response.status !== 200) {
@@ -27477,7 +27522,7 @@ function createMemberApi(httpClient) {
27477
27522
  async updateMemberRole(input) {
27478
27523
  const response = await httpClient.request({
27479
27524
  method: "PATCH",
27480
- path: `/v1/organization/members/${input.userId}`,
27525
+ path: `/v1/projects/${input.projectId}/members/${input.userId}`,
27481
27526
  bearerToken: input.bearerToken,
27482
27527
  body: { role: input.role }
27483
27528
  });
@@ -27489,7 +27534,7 @@ function createMemberApi(httpClient) {
27489
27534
  async removeMember(input) {
27490
27535
  const response = await httpClient.request({
27491
27536
  method: "DELETE",
27492
- path: `/v1/organization/members/${input.userId}`,
27537
+ path: `/v1/projects/${input.projectId}/members/${input.userId}`,
27493
27538
  bearerToken: input.bearerToken
27494
27539
  });
27495
27540
  if (response.status !== 200) {
@@ -27503,7 +27548,7 @@ function formatMembersTable(members) {
27503
27548
  if (members.length === 0) {
27504
27549
  return "No members found.";
27505
27550
  }
27506
- return members.map((m) => `${m.user_id} | ${m.email} | ${m.role} | joined=${m.joined_at}`).join("\n");
27551
+ return members.map((m) => `${m.user_id} | ${m.email} | ${m.role} | type=${m.membership_type ?? "collaborator"} | joined=${m.created_at}`).join("\n");
27507
27552
  }
27508
27553
  function formatInvitesTable(invites) {
27509
27554
  if (invites.length === 0) {
@@ -27531,7 +27576,7 @@ function mapErrorToExitCode12(error) {
27531
27576
  }
27532
27577
  async function listMembersCommand(input, api) {
27533
27578
  try {
27534
- const result = await api.listMembers({ bearerToken: input.bearerToken });
27579
+ const result = await api.listMembers({ bearerToken: input.bearerToken, projectId: input.projectId });
27535
27580
  return {
27536
27581
  exitCode: 0,
27537
27582
  output: input.json ? JSON.stringify(result) : formatMembersTable(result.members)
@@ -27545,7 +27590,7 @@ async function listMembersCommand(input, api) {
27545
27590
  }
27546
27591
  async function listInvitesCommand(input, api) {
27547
27592
  try {
27548
- const result = await api.listInvites({ bearerToken: input.bearerToken });
27593
+ const result = await api.listInvites({ bearerToken: input.bearerToken, projectId: input.projectId });
27549
27594
  return {
27550
27595
  exitCode: 0,
27551
27596
  output: input.json ? JSON.stringify(result) : formatInvitesTable(result.invites)
@@ -27559,7 +27604,12 @@ async function listInvitesCommand(input, api) {
27559
27604
  }
27560
27605
  async function inviteMemberCommand(input, api) {
27561
27606
  try {
27562
- const result = await api.inviteMember({ bearerToken: input.bearerToken, email: input.email, role: input.role });
27607
+ const result = await api.inviteMember({
27608
+ bearerToken: input.bearerToken,
27609
+ projectId: input.projectId,
27610
+ email: input.email,
27611
+ role: input.role
27612
+ });
27563
27613
  return {
27564
27614
  exitCode: 0,
27565
27615
  output: input.json ? JSON.stringify(result) : `Invite sent: ${result.invite.invite_id} \u2192 ${result.invite.email} (${result.invite.role})`
@@ -27573,7 +27623,7 @@ async function inviteMemberCommand(input, api) {
27573
27623
  }
27574
27624
  async function cancelInviteCommand(input, api) {
27575
27625
  try {
27576
- const result = await api.cancelInvite({ bearerToken: input.bearerToken, inviteId: input.inviteId });
27626
+ const result = await api.cancelInvite({ bearerToken: input.bearerToken, projectId: input.projectId, inviteId: input.inviteId });
27577
27627
  return {
27578
27628
  exitCode: 0,
27579
27629
  output: input.json ? JSON.stringify(result) : `Invite cancelled: ${result.invite.invite_id}`
@@ -27587,7 +27637,12 @@ async function cancelInviteCommand(input, api) {
27587
27637
  }
27588
27638
  async function updateMemberRoleCommand(input, api) {
27589
27639
  try {
27590
- const result = await api.updateMemberRole({ bearerToken: input.bearerToken, userId: input.userId, role: input.role });
27640
+ const result = await api.updateMemberRole({
27641
+ bearerToken: input.bearerToken,
27642
+ projectId: input.projectId,
27643
+ userId: input.userId,
27644
+ role: input.role
27645
+ });
27591
27646
  return {
27592
27647
  exitCode: 0,
27593
27648
  output: input.json ? JSON.stringify(result) : `Role updated: ${result.member.user_id} \u2192 ${result.member.role}`
@@ -27601,7 +27656,7 @@ async function updateMemberRoleCommand(input, api) {
27601
27656
  }
27602
27657
  async function removeMemberCommand(input, api) {
27603
27658
  try {
27604
- const result = await api.removeMember({ bearerToken: input.bearerToken, userId: input.userId });
27659
+ const result = await api.removeMember({ bearerToken: input.bearerToken, projectId: input.projectId, userId: input.userId });
27605
27660
  return {
27606
27661
  exitCode: 0,
27607
27662
  output: input.json ? JSON.stringify(result) : `Member removed: ${result.member.user_id}`
@@ -27630,7 +27685,7 @@ async function listMembersWithAuthCommand(input, dependencies) {
27630
27685
  createApi: createAuthenticatedMemberApi,
27631
27686
  dependencies,
27632
27687
  runCommand: (authState, api) => listMembersCommand(
27633
- { bearerToken: authState.bearer_token, ...input.json === void 0 ? {} : { json: input.json } },
27688
+ { bearerToken: authState.bearer_token, projectId: input.projectId, ...input.json === void 0 ? {} : { json: input.json } },
27634
27689
  api
27635
27690
  )
27636
27691
  });
@@ -27640,7 +27695,7 @@ async function listInvitesWithAuthCommand(input, dependencies) {
27640
27695
  createApi: createAuthenticatedMemberApi,
27641
27696
  dependencies,
27642
27697
  runCommand: (authState, api) => listInvitesCommand(
27643
- { bearerToken: authState.bearer_token, ...input.json === void 0 ? {} : { json: input.json } },
27698
+ { bearerToken: authState.bearer_token, projectId: input.projectId, ...input.json === void 0 ? {} : { json: input.json } },
27644
27699
  api
27645
27700
  )
27646
27701
  });
@@ -27650,7 +27705,13 @@ async function inviteMemberWithAuthCommand(input, dependencies) {
27650
27705
  createApi: createAuthenticatedMemberApi,
27651
27706
  dependencies,
27652
27707
  runCommand: (authState, api) => inviteMemberCommand(
27653
- { bearerToken: authState.bearer_token, email: input.email, role: input.role, ...input.json === void 0 ? {} : { json: input.json } },
27708
+ {
27709
+ bearerToken: authState.bearer_token,
27710
+ projectId: input.projectId,
27711
+ email: input.email,
27712
+ role: input.role,
27713
+ ...input.json === void 0 ? {} : { json: input.json }
27714
+ },
27654
27715
  api
27655
27716
  )
27656
27717
  });
@@ -27660,7 +27721,12 @@ async function cancelInviteWithAuthCommand(input, dependencies) {
27660
27721
  createApi: createAuthenticatedMemberApi,
27661
27722
  dependencies,
27662
27723
  runCommand: (authState, api) => cancelInviteCommand(
27663
- { bearerToken: authState.bearer_token, inviteId: input.inviteId, ...input.json === void 0 ? {} : { json: input.json } },
27724
+ {
27725
+ bearerToken: authState.bearer_token,
27726
+ projectId: input.projectId,
27727
+ inviteId: input.inviteId,
27728
+ ...input.json === void 0 ? {} : { json: input.json }
27729
+ },
27664
27730
  api
27665
27731
  )
27666
27732
  });
@@ -27670,7 +27736,13 @@ async function updateMemberRoleWithAuthCommand(input, dependencies) {
27670
27736
  createApi: createAuthenticatedMemberApi,
27671
27737
  dependencies,
27672
27738
  runCommand: (authState, api) => updateMemberRoleCommand(
27673
- { bearerToken: authState.bearer_token, userId: input.userId, role: input.role, ...input.json === void 0 ? {} : { json: input.json } },
27739
+ {
27740
+ bearerToken: authState.bearer_token,
27741
+ projectId: input.projectId,
27742
+ userId: input.userId,
27743
+ role: input.role,
27744
+ ...input.json === void 0 ? {} : { json: input.json }
27745
+ },
27674
27746
  api
27675
27747
  )
27676
27748
  });
@@ -27680,7 +27752,12 @@ async function removeMemberWithAuthCommand(input, dependencies) {
27680
27752
  createApi: createAuthenticatedMemberApi,
27681
27753
  dependencies,
27682
27754
  runCommand: (authState, api) => removeMemberCommand(
27683
- { bearerToken: authState.bearer_token, userId: input.userId, ...input.json === void 0 ? {} : { json: input.json } },
27755
+ {
27756
+ bearerToken: authState.bearer_token,
27757
+ projectId: input.projectId,
27758
+ userId: input.userId,
27759
+ ...input.json === void 0 ? {} : { json: input.json }
27760
+ },
27684
27761
  api
27685
27762
  )
27686
27763
  });
@@ -28504,6 +28581,78 @@ async function handleBillingCommand(parsedArgv, dependencies) {
28504
28581
  }
28505
28582
  async function handleProjectCommand(parsedArgv, dependencies) {
28506
28583
  const action = requirePositional(parsedArgv, 1, "action");
28584
+ if (action === "members") {
28585
+ const membersAction = requirePositional(parsedArgv, 2, "members-action");
28586
+ const projectId = readStringOption(parsedArgv, "project-id");
28587
+ if (projectId === void 0) {
28588
+ throw new CliInputError("Missing required option --project-id.");
28589
+ }
28590
+ if (membersAction === "list") {
28591
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
28592
+ ensureNoExtraPositionals(parsedArgv, 3);
28593
+ return await (dependencies.listMembersCommand ?? listMembersWithAuthCommand)(
28594
+ appendCommonAuthOptions(parsedArgv, { projectId })
28595
+ );
28596
+ }
28597
+ if (membersAction === "invites") {
28598
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
28599
+ ensureNoExtraPositionals(parsedArgv, 3);
28600
+ return await (dependencies.listInvitesCommand ?? listInvitesWithAuthCommand)(
28601
+ appendCommonAuthOptions(parsedArgv, { projectId })
28602
+ );
28603
+ }
28604
+ if (membersAction === "invite") {
28605
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "email", "role"]);
28606
+ ensureNoExtraPositionals(parsedArgv, 3);
28607
+ const email = readStringOption(parsedArgv, "email");
28608
+ if (email === void 0) {
28609
+ throw new CliInputError("Missing required option --email.");
28610
+ }
28611
+ const role = readStringOption(parsedArgv, "role");
28612
+ if (role === void 0) {
28613
+ throw new CliInputError("Missing required option --role.");
28614
+ }
28615
+ return await (dependencies.inviteMemberCommand ?? inviteMemberWithAuthCommand)(
28616
+ appendCommonAuthOptions(parsedArgv, { projectId, email, role })
28617
+ );
28618
+ }
28619
+ if (membersAction === "cancel-invite") {
28620
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
28621
+ ensureNoExtraPositionals(parsedArgv, 4);
28622
+ return await (dependencies.cancelInviteCommand ?? cancelInviteWithAuthCommand)(
28623
+ appendCommonAuthOptions(parsedArgv, {
28624
+ projectId,
28625
+ inviteId: requirePositional(parsedArgv, 3, "invite-id")
28626
+ })
28627
+ );
28628
+ }
28629
+ if (membersAction === "update-role") {
28630
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "role"]);
28631
+ ensureNoExtraPositionals(parsedArgv, 4);
28632
+ const role = readStringOption(parsedArgv, "role");
28633
+ if (role === void 0) {
28634
+ throw new CliInputError("Missing required option --role.");
28635
+ }
28636
+ return await (dependencies.updateMemberRoleCommand ?? updateMemberRoleWithAuthCommand)(
28637
+ appendCommonAuthOptions(parsedArgv, {
28638
+ projectId,
28639
+ userId: requirePositional(parsedArgv, 3, "user-id"),
28640
+ role
28641
+ })
28642
+ );
28643
+ }
28644
+ if (membersAction === "remove") {
28645
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
28646
+ ensureNoExtraPositionals(parsedArgv, 4);
28647
+ return await (dependencies.removeMemberCommand ?? removeMemberWithAuthCommand)(
28648
+ appendCommonAuthOptions(parsedArgv, {
28649
+ projectId,
28650
+ userId: requirePositional(parsedArgv, 3, "user-id")
28651
+ })
28652
+ );
28653
+ }
28654
+ throw new CliInputError("Unknown project members command.");
28655
+ }
28507
28656
  if (action === "list") {
28508
28657
  expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "limit"]);
28509
28658
  ensureNoExtraPositionals(parsedArgv, 2);
@@ -28797,66 +28946,10 @@ async function handleProbeCommand(parsedArgv, dependencies) {
28797
28946
  }
28798
28947
  throw new CliInputError("Unknown probe command.");
28799
28948
  }
28800
- async function handleMemberCommand(parsedArgv, dependencies) {
28801
- const action = requirePositional(parsedArgv, 1, "action");
28802
- if (action === "list") {
28803
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json"]);
28804
- ensureNoExtraPositionals(parsedArgv, 2);
28805
- return await (dependencies.listMembersCommand ?? listMembersWithAuthCommand)(appendCommonAuthOptions(parsedArgv, {}));
28806
- }
28807
- if (action === "invites") {
28808
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json"]);
28809
- ensureNoExtraPositionals(parsedArgv, 2);
28810
- return await (dependencies.listInvitesCommand ?? listInvitesWithAuthCommand)(appendCommonAuthOptions(parsedArgv, {}));
28811
- }
28812
- if (action === "invite") {
28813
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "email", "role"]);
28814
- ensureNoExtraPositionals(parsedArgv, 2);
28815
- const email = readStringOption(parsedArgv, "email");
28816
- if (email === void 0) {
28817
- throw new CliInputError("Missing required option --email.");
28818
- }
28819
- const role = readStringOption(parsedArgv, "role");
28820
- if (role === void 0) {
28821
- throw new CliInputError("Missing required option --role.");
28822
- }
28823
- return await (dependencies.inviteMemberCommand ?? inviteMemberWithAuthCommand)(
28824
- appendCommonAuthOptions(parsedArgv, { email, role })
28825
- );
28826
- }
28827
- if (action === "cancel-invite") {
28828
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json"]);
28829
- ensureNoExtraPositionals(parsedArgv, 3);
28830
- return await (dependencies.cancelInviteCommand ?? cancelInviteWithAuthCommand)(
28831
- appendCommonAuthOptions(parsedArgv, {
28832
- inviteId: requirePositional(parsedArgv, 2, "invite-id")
28833
- })
28834
- );
28835
- }
28836
- if (action === "update-role") {
28837
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "role"]);
28838
- ensureNoExtraPositionals(parsedArgv, 3);
28839
- const role = readStringOption(parsedArgv, "role");
28840
- if (role === void 0) {
28841
- throw new CliInputError("Missing required option --role.");
28842
- }
28843
- return await (dependencies.updateMemberRoleCommand ?? updateMemberRoleWithAuthCommand)(
28844
- appendCommonAuthOptions(parsedArgv, {
28845
- userId: requirePositional(parsedArgv, 2, "user-id"),
28846
- role
28847
- })
28848
- );
28849
- }
28850
- if (action === "remove") {
28851
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json"]);
28852
- ensureNoExtraPositionals(parsedArgv, 3);
28853
- return await (dependencies.removeMemberCommand ?? removeMemberWithAuthCommand)(
28854
- appendCommonAuthOptions(parsedArgv, {
28855
- userId: requirePositional(parsedArgv, 2, "user-id")
28856
- })
28857
- );
28858
- }
28859
- throw new CliInputError("Unknown member command.");
28949
+ function handleMemberCommand(parsedArgv, dependencies) {
28950
+ void parsedArgv;
28951
+ void dependencies;
28952
+ throw new CliInputError("Use `debugbundle project members ... --project-id <id>` for project collaboration commands.");
28860
28953
  }
28861
28954
  async function handleWebhookCommand(parsedArgv, dependencies) {
28862
28955
  const action = requirePositional(parsedArgv, 1, "action");
@@ -29519,7 +29612,7 @@ ${formatUsage()}`
29519
29612
  return await (dependencies.verifyLocalCommand ?? verifyLocalCommand)(readBooleanOption(parsedArgv, "json") === true ? { json: true } : {});
29520
29613
  }
29521
29614
  if (subcommand === "cloud") {
29522
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "service", "environment", "max-age-minutes", "trigger-5xx"]);
29615
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "service", "environment", "max-age-minutes", "trigger-5xx", "trigger-4xx"]);
29523
29616
  ensureNoExtraPositionals(parsedArgv, 2);
29524
29617
  const projectId = readStringOption(parsedArgv, "project-id");
29525
29618
  if (projectId === void 0) {
@@ -29537,6 +29630,10 @@ ${formatUsage()}`
29537
29630
  if (readBooleanOption(parsedArgv, "trigger-5xx") === true) {
29538
29631
  input.trigger5xx = true;
29539
29632
  }
29633
+ const trigger4xxStatus = readIntegerOption(parsedArgv, "trigger-4xx");
29634
+ if (trigger4xxStatus !== void 0) {
29635
+ input.trigger4xxStatus = trigger4xxStatus;
29636
+ }
29540
29637
  return await (dependencies.verifyCloudCommand ?? verifyCloudCommand)(input);
29541
29638
  }
29542
29639
  throw new CliInputError("Unknown verify command.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugbundle/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
5
  "description": "Command-line interface for DebugBundle",
6
6
  "license": "AGPL-3.0-only",