@debugbundle/cli 0.1.3 → 0.1.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 +420 -33
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -16654,6 +16654,32 @@ var STORAGE_SCHEMA_MIGRATIONS = [
16654
16654
  statements: [
16655
16655
  "ALTER TABLE webhook_deliveries ALTER COLUMN incident_id DROP NOT NULL"
16656
16656
  ]
16657
+ }),
16658
+ defineStorageSchemaMigration({
16659
+ id: "202605130002_add_slack_destinations",
16660
+ description: "Add reusable encrypted Slack alert destinations scoped to organizations.",
16661
+ statements: [
16662
+ `
16663
+ CREATE TABLE IF NOT EXISTS slack_destinations (
16664
+ id uuid PRIMARY KEY,
16665
+ organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
16666
+ slack_team_id text NOT NULL,
16667
+ slack_team_name text,
16668
+ slack_channel_id text NOT NULL,
16669
+ slack_channel_name text,
16670
+ webhook_url_ciphertext text NOT NULL,
16671
+ installed_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
16672
+ is_active boolean NOT NULL DEFAULT true,
16673
+ created_at timestamptz NOT NULL DEFAULT now(),
16674
+ updated_at timestamptz NOT NULL DEFAULT now(),
16675
+ UNIQUE (organization_id, slack_team_id, slack_channel_id)
16676
+ )
16677
+ `,
16678
+ `
16679
+ CREATE INDEX IF NOT EXISTS slack_destinations_org_active_idx
16680
+ ON slack_destinations (organization_id, is_active, created_at)
16681
+ `
16682
+ ]
16657
16683
  })
16658
16684
  ];
16659
16685
 
@@ -18317,7 +18343,7 @@ function createWeeklyReportApi(client) {
18317
18343
  );
18318
18344
  },
18319
18345
  async createWeeklyReportChannel(input) {
18320
- const config = input.channel === "email" ? { to: input.config.to } : { webhook_url: input.config.webhookUrl };
18346
+ const config = input.channel === "email" ? { to: input.config.to } : "webhookUrl" in input.config ? { webhook_url: input.config.webhookUrl } : { slack_destination_id: input.config.slackDestinationId };
18321
18347
  return expectChannel(
18322
18348
  client.request({
18323
18349
  method: "POST",
@@ -18340,7 +18366,7 @@ function createWeeklyReportApi(client) {
18340
18366
  async updateWeeklyReportChannel(input) {
18341
18367
  const body = {};
18342
18368
  if (input.config !== void 0) {
18343
- body["config"] = "to" in input.config ? { to: input.config.to } : { webhook_url: input.config.webhookUrl };
18369
+ body["config"] = "to" in input.config ? { to: input.config.to } : "webhookUrl" in input.config ? { webhook_url: input.config.webhookUrl } : { slack_destination_id: input.config.slackDestinationId };
18344
18370
  }
18345
18371
  if (input.schedule !== void 0) {
18346
18372
  body["schedule"] = {
@@ -18809,6 +18835,121 @@ function createGitHubManagementApi(client) {
18809
18835
  };
18810
18836
  }
18811
18837
 
18838
+ // ../../packages/slack-client/src/index.ts
18839
+ var SlackDestinationRecordSchema = external_exports.object({
18840
+ slack_destination_id: external_exports.string(),
18841
+ organization_id: external_exports.string(),
18842
+ slack_team_id: external_exports.string(),
18843
+ slack_team_name: external_exports.string().nullable(),
18844
+ slack_channel_id: external_exports.string(),
18845
+ slack_channel_name: external_exports.string().nullable(),
18846
+ installed_by_member_id: external_exports.string().nullable(),
18847
+ is_active: external_exports.boolean(),
18848
+ created_at: external_exports.string(),
18849
+ updated_at: external_exports.string()
18850
+ }).strict();
18851
+ var SlackDestinationListResponseSchema = external_exports.object({
18852
+ destinations: external_exports.array(SlackDestinationRecordSchema)
18853
+ }).strict();
18854
+ var SlackInstallUrlResponseSchema = external_exports.object({
18855
+ install_url: external_exports.string().url()
18856
+ }).strict();
18857
+ var SlackDestinationTestResponseSchema = external_exports.object({
18858
+ delivered: external_exports.boolean()
18859
+ }).strict();
18860
+ var ApiErrorResponseSchema9 = external_exports.object({
18861
+ error: external_exports.string()
18862
+ }).strict();
18863
+ var SlackApiError = class extends Error {
18864
+ status;
18865
+ code;
18866
+ constructor(status, code) {
18867
+ super(`slack_api_error: ${status}:${code}`);
18868
+ this.status = status;
18869
+ this.code = code;
18870
+ }
18871
+ };
18872
+ function parseApiError9(status, body) {
18873
+ const parsed = ApiErrorResponseSchema9.safeParse(body);
18874
+ if (!parsed.success) {
18875
+ throw new SlackApiError(status, "unknown_error");
18876
+ }
18877
+ throw new SlackApiError(status, parsed.data.error);
18878
+ }
18879
+ function buildQuery4(input) {
18880
+ const params = new URLSearchParams();
18881
+ for (const [key, value] of Object.entries(input)) {
18882
+ if (value !== void 0) {
18883
+ params.set(key, String(value));
18884
+ }
18885
+ }
18886
+ const query = params.toString();
18887
+ return query.length === 0 ? "" : `?${query}`;
18888
+ }
18889
+ function createSlackApi(client) {
18890
+ return {
18891
+ async getSlackInstallUrl(input) {
18892
+ const response = await client.request({
18893
+ method: "GET",
18894
+ path: `/v1/slack/app/install-url${buildQuery4({
18895
+ project_id: input.projectId,
18896
+ return_to: input.returnTo
18897
+ })}`,
18898
+ bearerToken: input.bearerToken
18899
+ });
18900
+ if (response.status < 200 || response.status >= 300) {
18901
+ parseApiError9(response.status, response.body);
18902
+ }
18903
+ const parsed = SlackInstallUrlResponseSchema.safeParse(response.body);
18904
+ if (!parsed.success) {
18905
+ throw new SlackApiError(response.status, "invalid_response_shape");
18906
+ }
18907
+ return parsed.data.install_url;
18908
+ },
18909
+ async listSlackDestinations(input) {
18910
+ const response = await client.request({
18911
+ method: "GET",
18912
+ path: `/v1/projects/${input.projectId}/slack/destinations`,
18913
+ bearerToken: input.bearerToken
18914
+ });
18915
+ if (response.status < 200 || response.status >= 300) {
18916
+ parseApiError9(response.status, response.body);
18917
+ }
18918
+ const parsed = SlackDestinationListResponseSchema.safeParse(response.body);
18919
+ if (!parsed.success) {
18920
+ throw new SlackApiError(response.status, "invalid_response_shape");
18921
+ }
18922
+ return parsed.data.destinations;
18923
+ },
18924
+ async testSlackDestination(input) {
18925
+ const response = await client.request({
18926
+ method: "POST",
18927
+ path: `/v1/projects/${input.projectId}/slack/destinations/${input.destinationId}/test`,
18928
+ bearerToken: input.bearerToken
18929
+ });
18930
+ if (response.status < 200 || response.status >= 300) {
18931
+ parseApiError9(response.status, response.body);
18932
+ }
18933
+ const parsed = SlackDestinationTestResponseSchema.safeParse(response.body);
18934
+ if (!parsed.success || parsed.data.delivered !== true) {
18935
+ throw new SlackApiError(response.status, "invalid_response_shape");
18936
+ }
18937
+ return { delivered: true };
18938
+ },
18939
+ async deleteSlackDestination(input) {
18940
+ const response = await client.request({
18941
+ method: "DELETE",
18942
+ path: `/v1/projects/${input.projectId}/slack/destinations/${input.destinationId}`,
18943
+ bearerToken: input.bearerToken
18944
+ });
18945
+ if (response.status < 200 || response.status >= 300) {
18946
+ parseApiError9(response.status, response.body);
18947
+ }
18948
+ return { slack_destination_id: input.destinationId };
18949
+ }
18950
+ };
18951
+ }
18952
+
18812
18953
  // src/auth-context.ts
18813
18954
  function normalizeBaseUrl(baseUrl) {
18814
18955
  return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
@@ -18984,6 +19125,29 @@ async function createAuthenticatedWeeklyReportApi(input, dependencies) {
18984
19125
  api: createApi(httpClient)
18985
19126
  };
18986
19127
  }
19128
+ async function createAuthenticatedSlackApi(input, dependencies) {
19129
+ const readAuthState = dependencies?.readAuthState ?? readCliAuthState;
19130
+ const authStateInput = {};
19131
+ if (input.authFilePath !== void 0) {
19132
+ authStateInput.authFilePath = input.authFilePath;
19133
+ }
19134
+ const authState = await readAuthState(authStateInput);
19135
+ const createHttpClient = dependencies?.createHttpClient ?? ((clientInput) => {
19136
+ const httpClientDependencies = {};
19137
+ if (dependencies?.fetchImpl !== void 0) {
19138
+ httpClientDependencies.fetchImpl = dependencies.fetchImpl;
19139
+ }
19140
+ return createCliHttpClient(clientInput, httpClientDependencies);
19141
+ });
19142
+ const httpClient = createHttpClient({
19143
+ baseUrl: authState.base_url
19144
+ });
19145
+ const createApi = dependencies?.createApi ?? createSlackApi;
19146
+ return {
19147
+ authState,
19148
+ api: createApi(httpClient)
19149
+ };
19150
+ }
18987
19151
  async function createAuthenticatedProjectManagementApi(input, dependencies) {
18988
19152
  const readAuthState = dependencies?.readAuthState ?? readCliAuthState;
18989
19153
  const authStateInput = {};
@@ -19169,7 +19333,7 @@ var LoginCommandInputSchema = external_exports.object({
19169
19333
  });
19170
19334
  }
19171
19335
  });
19172
- var ApiErrorResponseSchema9 = external_exports.object({
19336
+ var ApiErrorResponseSchema10 = external_exports.object({
19173
19337
  error: external_exports.string()
19174
19338
  }).strict();
19175
19339
  var DeviceStartResponseSchema = external_exports.object({
@@ -19345,7 +19509,7 @@ async function requestJson(input, dependencies) {
19345
19509
  });
19346
19510
  const body = await parseResponseBody2(response);
19347
19511
  if (response.status < 200 || response.status >= 300) {
19348
- const parsedError = ApiErrorResponseSchema9.safeParse(body);
19512
+ const parsedError = ApiErrorResponseSchema10.safeParse(body);
19349
19513
  throw new LoginApiError(response.status, parsedError.success ? parsedError.data.error : "unknown_error");
19350
19514
  }
19351
19515
  return body;
@@ -25095,6 +25259,10 @@ var CLI_USAGE_LINES = [
25095
25259
  " debugbundle alert create --project-id <id> --channel <channel> --condition <condition> [--service-id <id>] [--severity-min <level>] --config-json <json> [--is-enabled <true|false>] [--auth-file <path>] [--json]",
25096
25260
  " debugbundle alert update <alert-id> [--service-id <id|null>] [--channel <channel>] [--condition <condition>] [--severity-min <level|null>] [--config-json <json|null>] [--is-enabled <true|false>] [--auth-file <path>] [--json]",
25097
25261
  " debugbundle alert delete <alert-id> [--auth-file <path>] [--json]",
25262
+ " debugbundle slack list --project-id <id> [--auth-file <path>] [--json]",
25263
+ " debugbundle slack connect-url --project-id <id> [--return-to </projects/...>] [--auth-file <path>] [--json]",
25264
+ " debugbundle slack test <destination-id> --project-id <id> [--auth-file <path>] [--json]",
25265
+ " debugbundle slack delete <destination-id> --project-id <id> [--auth-file <path>] [--json]",
25098
25266
  " debugbundle webhook list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
25099
25267
  " debugbundle webhook create --project-id <id> --url <url> --event <event[,event]> [--environment <env[,env]>] [--service <svc[,svc]>] [--severity-min <level>] [--bundle-type <type[,type]>] [--verification <true|false>] [--is-enabled <true|false>] [--auth-file <path>] [--json]",
25100
25268
  " debugbundle webhook update <webhook-id> [--url <url>] [--event <event[,event]>] [--environment <env[,env]>] [--service <svc[,svc]>] [--severity-min <level>] [--bundle-type <type[,type]>] [--verification <true|false>] [--is-enabled <true|false>] [--auth-file <path>] [--json]",
@@ -26872,8 +27040,153 @@ async function deleteWeeklyReportChannelWithAuthCommand(input, dependencies) {
26872
27040
  });
26873
27041
  }
26874
27042
 
26875
- // src/billing-commands.ts
27043
+ // src/slack-commands.ts
26876
27044
  function mapErrorToExitCode10(error) {
27045
+ if (!(error instanceof SlackApiError)) {
27046
+ return 1;
27047
+ }
27048
+ if (error.status === 401) {
27049
+ return 2;
27050
+ }
27051
+ if (error.status === 404) {
27052
+ return 3;
27053
+ }
27054
+ if (error.status === 400 || error.status === 403) {
27055
+ return 4;
27056
+ }
27057
+ return 1;
27058
+ }
27059
+ function formatSlackDestinationTable(destinations) {
27060
+ if (destinations.length === 0) {
27061
+ return "No Slack destinations found.";
27062
+ }
27063
+ return destinations.map((destination) => {
27064
+ const workspace = destination.slack_team_name ?? destination.slack_team_id;
27065
+ const channel = destination.slack_channel_name ?? destination.slack_channel_id;
27066
+ return `${destination.slack_destination_id} | ${destination.is_active ? "active" : "inactive"} | ${workspace} | ${channel}`;
27067
+ }).join("\n");
27068
+ }
27069
+ async function listSlackDestinationsCommand(input, api) {
27070
+ try {
27071
+ const destinations = await api.listSlackDestinations({
27072
+ bearerToken: input.bearerToken,
27073
+ projectId: input.projectId
27074
+ });
27075
+ return {
27076
+ exitCode: 0,
27077
+ output: input.json ? JSON.stringify({ destinations }) : formatSlackDestinationTable(destinations)
27078
+ };
27079
+ } catch (error) {
27080
+ return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27081
+ }
27082
+ }
27083
+ async function listSlackDestinationsWithAuthCommand(input, dependencies) {
27084
+ return runAuthenticatedCliCommand(input, {
27085
+ createApi: createAuthenticatedSlackApi,
27086
+ dependencies,
27087
+ runCommand: (authState, api) => listSlackDestinationsCommand(
27088
+ {
27089
+ bearerToken: authState.bearer_token,
27090
+ projectId: input.projectId,
27091
+ ...input.json !== void 0 ? { json: input.json } : {}
27092
+ },
27093
+ api
27094
+ )
27095
+ });
27096
+ }
27097
+ async function getSlackConnectUrlCommand(input, api) {
27098
+ try {
27099
+ const installUrl = await api.getSlackInstallUrl({
27100
+ bearerToken: input.bearerToken,
27101
+ projectId: input.projectId,
27102
+ ...input.returnTo !== void 0 ? { returnTo: input.returnTo } : {}
27103
+ });
27104
+ return {
27105
+ exitCode: 0,
27106
+ output: input.json ? JSON.stringify({ install_url: installUrl }) : installUrl
27107
+ };
27108
+ } catch (error) {
27109
+ return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27110
+ }
27111
+ }
27112
+ async function getSlackConnectUrlWithAuthCommand(input, dependencies) {
27113
+ return runAuthenticatedCliCommand(input, {
27114
+ createApi: createAuthenticatedSlackApi,
27115
+ dependencies,
27116
+ runCommand: (authState, api) => getSlackConnectUrlCommand(
27117
+ {
27118
+ bearerToken: authState.bearer_token,
27119
+ projectId: input.projectId,
27120
+ ...input.returnTo !== void 0 ? { returnTo: input.returnTo } : {},
27121
+ ...input.json !== void 0 ? { json: input.json } : {}
27122
+ },
27123
+ api
27124
+ )
27125
+ });
27126
+ }
27127
+ async function testSlackDestinationCommand(input, api) {
27128
+ try {
27129
+ const delivery = await api.testSlackDestination({
27130
+ bearerToken: input.bearerToken,
27131
+ projectId: input.projectId,
27132
+ destinationId: input.destinationId
27133
+ });
27134
+ return {
27135
+ exitCode: 0,
27136
+ output: input.json ? JSON.stringify({ delivery }) : `Slack test message delivered for destination: ${input.destinationId}`
27137
+ };
27138
+ } catch (error) {
27139
+ return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27140
+ }
27141
+ }
27142
+ async function testSlackDestinationWithAuthCommand(input, dependencies) {
27143
+ return runAuthenticatedCliCommand(input, {
27144
+ createApi: createAuthenticatedSlackApi,
27145
+ dependencies,
27146
+ runCommand: (authState, api) => testSlackDestinationCommand(
27147
+ {
27148
+ bearerToken: authState.bearer_token,
27149
+ projectId: input.projectId,
27150
+ destinationId: input.destinationId,
27151
+ ...input.json !== void 0 ? { json: input.json } : {}
27152
+ },
27153
+ api
27154
+ )
27155
+ });
27156
+ }
27157
+ async function deleteSlackDestinationCommand(input, api) {
27158
+ try {
27159
+ const deleted = await api.deleteSlackDestination({
27160
+ bearerToken: input.bearerToken,
27161
+ projectId: input.projectId,
27162
+ destinationId: input.destinationId
27163
+ });
27164
+ return {
27165
+ exitCode: 0,
27166
+ output: input.json ? JSON.stringify({ destination: deleted }) : `Slack destination deleted: ${deleted.slack_destination_id}`
27167
+ };
27168
+ } catch (error) {
27169
+ return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27170
+ }
27171
+ }
27172
+ async function deleteSlackDestinationWithAuthCommand(input, dependencies) {
27173
+ return runAuthenticatedCliCommand(input, {
27174
+ createApi: createAuthenticatedSlackApi,
27175
+ dependencies,
27176
+ runCommand: (authState, api) => deleteSlackDestinationCommand(
27177
+ {
27178
+ bearerToken: authState.bearer_token,
27179
+ projectId: input.projectId,
27180
+ destinationId: input.destinationId,
27181
+ ...input.json !== void 0 ? { json: input.json } : {}
27182
+ },
27183
+ api
27184
+ )
27185
+ });
27186
+ }
27187
+
27188
+ // src/billing-commands.ts
27189
+ function mapErrorToExitCode11(error) {
26877
27190
  if (!(error instanceof BillingApiError)) {
26878
27191
  return 1;
26879
27192
  }
@@ -26921,7 +27234,7 @@ async function getBillingSummaryCommand(input, api) {
26921
27234
  output: input.json ? JSON.stringify({ billing }) : formatBillingSummary(billing)
26922
27235
  };
26923
27236
  } catch (error) {
26924
- return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27237
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
26925
27238
  }
26926
27239
  }
26927
27240
  async function increaseBillingCapacityCommand(input, api) {
@@ -26936,7 +27249,7 @@ async function increaseBillingCapacityCommand(input, api) {
26936
27249
  ${formatBillingSummary(billing)}`
26937
27250
  };
26938
27251
  } catch (error) {
26939
- return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27252
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
26940
27253
  }
26941
27254
  }
26942
27255
  async function scheduleBillingCapacityReductionCommand(input, api) {
@@ -26951,7 +27264,7 @@ async function scheduleBillingCapacityReductionCommand(input, api) {
26951
27264
  ${formatBillingSummary(billing)}`
26952
27265
  };
26953
27266
  } catch (error) {
26954
- return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27267
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
26955
27268
  }
26956
27269
  }
26957
27270
  async function cancelBillingCapacityReductionCommand(input, api) {
@@ -26963,7 +27276,7 @@ async function cancelBillingCapacityReductionCommand(input, api) {
26963
27276
  ${formatBillingSummary(billing)}`
26964
27277
  };
26965
27278
  } catch (error) {
26966
- return { exitCode: mapErrorToExitCode10(error), output: error instanceof Error ? error.message : String(error) };
27279
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
26967
27280
  }
26968
27281
  }
26969
27282
  async function getBillingSummaryWithAuthCommand(input, dependencies) {
@@ -27124,7 +27437,7 @@ function formatInvitesTable(invites) {
27124
27437
  }
27125
27438
  return invites.map((i) => `${i.invite_id} | ${i.email} | ${i.role} | expires=${i.expires_at}`).join("\n");
27126
27439
  }
27127
- function mapErrorToExitCode11(error) {
27440
+ function mapErrorToExitCode12(error) {
27128
27441
  if (!(error instanceof MemberApiError)) {
27129
27442
  return 1;
27130
27443
  }
@@ -27151,7 +27464,7 @@ async function listMembersCommand(input, api) {
27151
27464
  };
27152
27465
  } catch (error) {
27153
27466
  return {
27154
- exitCode: mapErrorToExitCode11(error),
27467
+ exitCode: mapErrorToExitCode12(error),
27155
27468
  output: error instanceof MemberApiError ? error.code : String(error)
27156
27469
  };
27157
27470
  }
@@ -27165,7 +27478,7 @@ async function listInvitesCommand(input, api) {
27165
27478
  };
27166
27479
  } catch (error) {
27167
27480
  return {
27168
- exitCode: mapErrorToExitCode11(error),
27481
+ exitCode: mapErrorToExitCode12(error),
27169
27482
  output: error instanceof MemberApiError ? error.code : String(error)
27170
27483
  };
27171
27484
  }
@@ -27179,7 +27492,7 @@ async function inviteMemberCommand(input, api) {
27179
27492
  };
27180
27493
  } catch (error) {
27181
27494
  return {
27182
- exitCode: mapErrorToExitCode11(error),
27495
+ exitCode: mapErrorToExitCode12(error),
27183
27496
  output: error instanceof MemberApiError ? error.code : String(error)
27184
27497
  };
27185
27498
  }
@@ -27193,7 +27506,7 @@ async function cancelInviteCommand(input, api) {
27193
27506
  };
27194
27507
  } catch (error) {
27195
27508
  return {
27196
- exitCode: mapErrorToExitCode11(error),
27509
+ exitCode: mapErrorToExitCode12(error),
27197
27510
  output: error instanceof MemberApiError ? error.code : String(error)
27198
27511
  };
27199
27512
  }
@@ -27207,7 +27520,7 @@ async function updateMemberRoleCommand(input, api) {
27207
27520
  };
27208
27521
  } catch (error) {
27209
27522
  return {
27210
- exitCode: mapErrorToExitCode11(error),
27523
+ exitCode: mapErrorToExitCode12(error),
27211
27524
  output: error instanceof MemberApiError ? error.code : String(error)
27212
27525
  };
27213
27526
  }
@@ -27221,7 +27534,7 @@ async function removeMemberCommand(input, api) {
27221
27534
  };
27222
27535
  } catch (error) {
27223
27536
  return {
27224
- exitCode: mapErrorToExitCode11(error),
27537
+ exitCode: mapErrorToExitCode12(error),
27225
27538
  output: error instanceof MemberApiError ? error.code : String(error)
27226
27539
  };
27227
27540
  }
@@ -27370,7 +27683,7 @@ function createProbeApi(httpClient) {
27370
27683
  }
27371
27684
  };
27372
27685
  }
27373
- function mapErrorToExitCode12(error) {
27686
+ function mapErrorToExitCode13(error) {
27374
27687
  if (!(error instanceof ProbeApiError)) {
27375
27688
  return 1;
27376
27689
  }
@@ -27423,7 +27736,7 @@ async function activateProbeCommand(input, api) {
27423
27736
  Trigger token: ${result.trigger_token}`
27424
27737
  };
27425
27738
  } catch (error) {
27426
- return { exitCode: mapErrorToExitCode12(error), output: error instanceof Error ? error.message : String(error) };
27739
+ return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27427
27740
  }
27428
27741
  }
27429
27742
  async function listActiveProbesCommand(input, api) {
@@ -27443,7 +27756,7 @@ async function listActiveProbesCommand(input, api) {
27443
27756
  output: result.activations.map((a) => `${a.activation_id} ${a.label_pattern} (${a.service}/${a.environment}) expires ${a.expires_at}`).join("\n")
27444
27757
  };
27445
27758
  } catch (error) {
27446
- return { exitCode: mapErrorToExitCode12(error), output: error instanceof Error ? error.message : String(error) };
27759
+ return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27447
27760
  }
27448
27761
  }
27449
27762
  async function deactivateProbeCommand(input, api) {
@@ -27461,7 +27774,7 @@ async function deactivateProbeCommand(input, api) {
27461
27774
  output: result.deactivated ? "Probe deactivated." : "Probe was already inactive."
27462
27775
  };
27463
27776
  } catch (error) {
27464
- return { exitCode: mapErrorToExitCode12(error), output: error instanceof Error ? error.message : String(error) };
27777
+ return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27465
27778
  }
27466
27779
  }
27467
27780
  async function createAuthenticatedProbeApi(input, dependencies) {
@@ -27511,7 +27824,7 @@ async function deactivateProbeWithAuthCommand(input, dependencies) {
27511
27824
  }
27512
27825
 
27513
27826
  // src/github-commands.ts
27514
- function mapErrorToExitCode13(error) {
27827
+ function mapErrorToExitCode14(error) {
27515
27828
  if (!(error instanceof GitHubManagementApiError)) {
27516
27829
  return 1;
27517
27830
  }
@@ -27572,7 +27885,7 @@ async function getGitHubStatusCommand(input, api) {
27572
27885
  ${formatProjectRepo(repo)}`
27573
27886
  };
27574
27887
  } catch (error) {
27575
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27888
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27576
27889
  }
27577
27890
  }
27578
27891
  async function listGitHubRepositoriesCommand(input, api) {
@@ -27583,7 +27896,7 @@ async function listGitHubRepositoriesCommand(input, api) {
27583
27896
  output: input.json ? JSON.stringify({ repositories }) : repositories.length === 0 ? "No GitHub repositories found." : repositories.map((repository) => `${repository.full_name} (${repository.default_branch})`).join("\n")
27584
27897
  };
27585
27898
  } catch (error) {
27586
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27899
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27587
27900
  }
27588
27901
  }
27589
27902
  async function setProjectGitHubRepoCommand(input, api) {
@@ -27606,7 +27919,7 @@ async function setProjectGitHubRepoCommand(input, api) {
27606
27919
  output: input.json ? JSON.stringify({ repo: assignedRepo }) : `Project repo set: ${formatProjectRepo(assignedRepo)}`
27607
27920
  };
27608
27921
  } catch (error) {
27609
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27922
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27610
27923
  }
27611
27924
  }
27612
27925
  async function removeProjectGitHubRepoCommand(input, api) {
@@ -27617,7 +27930,7 @@ async function removeProjectGitHubRepoCommand(input, api) {
27617
27930
  output: input.json ? JSON.stringify({ removed: true, project_id: input.projectId }) : `Project repo removed: ${input.projectId}`
27618
27931
  };
27619
27932
  } catch (error) {
27620
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27933
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27621
27934
  }
27622
27935
  }
27623
27936
  async function listProjectGitHubRulesCommand(input, api) {
@@ -27631,7 +27944,7 @@ async function listProjectGitHubRulesCommand(input, api) {
27631
27944
  output: input.json ? JSON.stringify({ rules }) : formatGitHubRuleTable(rules)
27632
27945
  };
27633
27946
  } catch (error) {
27634
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27947
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27635
27948
  }
27636
27949
  }
27637
27950
  async function listProjectGitHubDeliveriesCommand(input, api) {
@@ -27647,7 +27960,7 @@ async function listProjectGitHubDeliveriesCommand(input, api) {
27647
27960
  output: input.json ? JSON.stringify({ deliveries }) : formatGitHubDeliveryTable(deliveries)
27648
27961
  };
27649
27962
  } catch (error) {
27650
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27963
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27651
27964
  }
27652
27965
  }
27653
27966
  async function retryProjectGitHubDeliveryCommand(input, api) {
@@ -27662,7 +27975,7 @@ async function retryProjectGitHubDeliveryCommand(input, api) {
27662
27975
  output: input.json ? JSON.stringify({ delivery }) : `GitHub delivery retried: ${delivery.delivery_id} | ${delivery.status}`
27663
27976
  };
27664
27977
  } catch (error) {
27665
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
27978
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27666
27979
  }
27667
27980
  }
27668
27981
  async function createProjectGitHubRuleCommand(input, api) {
@@ -27685,7 +27998,7 @@ async function createProjectGitHubRuleCommand(input, api) {
27685
27998
  output: input.json ? JSON.stringify({ rule }) : `GitHub rule created: ${rule.rule_id}`
27686
27999
  };
27687
28000
  } catch (error) {
27688
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
28001
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27689
28002
  }
27690
28003
  }
27691
28004
  async function updateProjectGitHubRuleCommand(input, api) {
@@ -27709,7 +28022,7 @@ async function updateProjectGitHubRuleCommand(input, api) {
27709
28022
  output: input.json ? JSON.stringify({ rule }) : `GitHub rule updated: ${rule.rule_id}`
27710
28023
  };
27711
28024
  } catch (error) {
27712
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
28025
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27713
28026
  }
27714
28027
  }
27715
28028
  async function deleteProjectGitHubRuleCommand(input, api) {
@@ -27724,7 +28037,7 @@ async function deleteProjectGitHubRuleCommand(input, api) {
27724
28037
  output: input.json ? JSON.stringify({ deleted: true, project_id: input.projectId, rule_id: input.ruleId }) : `GitHub rule deleted: ${input.ruleId}`
27725
28038
  };
27726
28039
  } catch (error) {
27727
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
28040
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
27728
28041
  }
27729
28042
  }
27730
28043
  async function getGitHubStatusWithAuthCommand(input, dependencies) {
@@ -28722,6 +29035,67 @@ async function handleAlertCommand(parsedArgv, dependencies) {
28722
29035
  }
28723
29036
  throw new CliInputError("Unknown alert command.");
28724
29037
  }
29038
+ async function handleSlackCommand(parsedArgv, dependencies) {
29039
+ const action = requirePositional(parsedArgv, 1, "action");
29040
+ if (action === "list") {
29041
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
29042
+ ensureNoExtraPositionals(parsedArgv, 2);
29043
+ const projectId = readStringOption(parsedArgv, "project-id");
29044
+ if (projectId === void 0) {
29045
+ throw new CliInputError("Missing required option --project-id.");
29046
+ }
29047
+ return await (dependencies.listSlackDestinationsCommand ?? listSlackDestinationsWithAuthCommand)(
29048
+ appendCommonAuthOptions(parsedArgv, {
29049
+ projectId
29050
+ })
29051
+ );
29052
+ }
29053
+ if (action === "connect-url") {
29054
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "return-to"]);
29055
+ ensureNoExtraPositionals(parsedArgv, 2);
29056
+ const projectId = readStringOption(parsedArgv, "project-id");
29057
+ if (projectId === void 0) {
29058
+ throw new CliInputError("Missing required option --project-id.");
29059
+ }
29060
+ const input = appendCommonAuthOptions(parsedArgv, {
29061
+ projectId
29062
+ });
29063
+ const returnTo = readStringOption(parsedArgv, "return-to");
29064
+ if (returnTo !== void 0) {
29065
+ input.returnTo = returnTo;
29066
+ }
29067
+ return await (dependencies.getSlackConnectUrlCommand ?? getSlackConnectUrlWithAuthCommand)(input);
29068
+ }
29069
+ if (action === "test") {
29070
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
29071
+ ensureNoExtraPositionals(parsedArgv, 3);
29072
+ const projectId = readStringOption(parsedArgv, "project-id");
29073
+ if (projectId === void 0) {
29074
+ throw new CliInputError("Missing required option --project-id.");
29075
+ }
29076
+ return await (dependencies.testSlackDestinationCommand ?? testSlackDestinationWithAuthCommand)(
29077
+ appendCommonAuthOptions(parsedArgv, {
29078
+ projectId,
29079
+ destinationId: requirePositional(parsedArgv, 2, "destination-id")
29080
+ })
29081
+ );
29082
+ }
29083
+ if (action === "delete") {
29084
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
29085
+ ensureNoExtraPositionals(parsedArgv, 3);
29086
+ const projectId = readStringOption(parsedArgv, "project-id");
29087
+ if (projectId === void 0) {
29088
+ throw new CliInputError("Missing required option --project-id.");
29089
+ }
29090
+ return await (dependencies.deleteSlackDestinationCommand ?? deleteSlackDestinationWithAuthCommand)(
29091
+ appendCommonAuthOptions(parsedArgv, {
29092
+ projectId,
29093
+ destinationId: requirePositional(parsedArgv, 2, "destination-id")
29094
+ })
29095
+ );
29096
+ }
29097
+ throw new CliInputError("Unknown slack command.");
29098
+ }
28725
29099
  async function handleWeeklyReportCommand(parsedArgv, dependencies) {
28726
29100
  const action = requirePositional(parsedArgv, 1, "action");
28727
29101
  if (action === "list") {
@@ -28777,10 +29151,20 @@ async function handleWeeklyReportCommand(parsedArgv, dependencies) {
28777
29151
  if (config === void 0 || typeof config !== "object" || config === null) {
28778
29152
  throw new CliInputError("Missing required option --config-json.");
28779
29153
  }
29154
+ let weeklyReportConfig;
29155
+ if (channel === "slack") {
29156
+ if (typeof config["slack_destination_id"] === "string") {
29157
+ weeklyReportConfig = { slackDestinationId: String(config["slack_destination_id"]) };
29158
+ } else {
29159
+ weeklyReportConfig = { webhookUrl: String(config["webhook_url"]) };
29160
+ }
29161
+ } else {
29162
+ weeklyReportConfig = { to: config.to };
29163
+ }
28780
29164
  const input = appendCommonAuthOptions(parsedArgv, {
28781
29165
  projectId,
28782
29166
  channel,
28783
- config: channel === "slack" ? { webhookUrl: String(config["webhook_url"]) } : { to: config.to },
29167
+ config: weeklyReportConfig,
28784
29168
  schedule: {
28785
29169
  dayOfWeek,
28786
29170
  hourOfDay,
@@ -28821,7 +29205,7 @@ async function handleWeeklyReportCommand(parsedArgv, dependencies) {
28821
29205
  if (typeof config !== "object" || config === null) {
28822
29206
  throw new CliInputError("Invalid value for --config-json.");
28823
29207
  }
28824
- input.config = "webhook_url" in config ? { webhookUrl: String(config["webhook_url"]) } : { to: config.to };
29208
+ input.config = "slack_destination_id" in config ? { slackDestinationId: String(config["slack_destination_id"]) } : "webhook_url" in config ? { webhookUrl: String(config["webhook_url"]) } : { to: config.to };
28825
29209
  }
28826
29210
  const isEnabled = readBooleanStringOption(parsedArgv, "is-enabled");
28827
29211
  if (isEnabled !== void 0) {
@@ -29236,6 +29620,9 @@ ${formatUsage()}`
29236
29620
  if (command === "alert") {
29237
29621
  return await handleAlertCommand(parsedArgv, dependencies);
29238
29622
  }
29623
+ if (command === "slack") {
29624
+ return await handleSlackCommand(parsedArgv, dependencies);
29625
+ }
29239
29626
  if (command === "webhook") {
29240
29627
  return await handleWebhookCommand(parsedArgv, dependencies);
29241
29628
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugbundle/cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "description": "Command-line interface for DebugBundle",
6
6
  "license": "AGPL-3.0-only",