@debugbundle/cli 0.1.1 → 0.1.2
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.
- package/dist/main.cjs +971 -187
- package/package.json +2 -2
package/dist/main.cjs
CHANGED
|
@@ -14547,6 +14547,26 @@ var InlineProbeDataSchema = external_exports.object({
|
|
|
14547
14547
|
version: external_exports.literal(1),
|
|
14548
14548
|
items: external_exports.array(InlineProbeDataItemSchema)
|
|
14549
14549
|
}).strict();
|
|
14550
|
+
var RuntimeMemoryStatsSchema = external_exports.object({
|
|
14551
|
+
rss: external_exports.number().nonnegative().nullable(),
|
|
14552
|
+
heap_total: external_exports.number().nonnegative().nullable(),
|
|
14553
|
+
heap_used: external_exports.number().nonnegative().nullable(),
|
|
14554
|
+
external: external_exports.number().nonnegative().nullable(),
|
|
14555
|
+
peak: external_exports.number().nonnegative().nullable()
|
|
14556
|
+
}).strict();
|
|
14557
|
+
var BackendRuntimePayloadSchema = external_exports.object({
|
|
14558
|
+
version: external_exports.string().min(1),
|
|
14559
|
+
platform: external_exports.string().min(1).nullable().optional(),
|
|
14560
|
+
arch: external_exports.string().min(1).nullable().optional(),
|
|
14561
|
+
pid: external_exports.number().int().nonnegative().nullable().optional(),
|
|
14562
|
+
cwd: external_exports.string().min(1).nullable().optional(),
|
|
14563
|
+
uptime_sec: external_exports.number().nonnegative().nullable().optional(),
|
|
14564
|
+
hostname: external_exports.string().min(1).nullable().optional(),
|
|
14565
|
+
thread_id: external_exports.union([external_exports.string(), external_exports.number()]).nullable().optional(),
|
|
14566
|
+
framework_version: external_exports.string().min(1).nullable().optional(),
|
|
14567
|
+
memory: RuntimeMemoryStatsSchema.nullable().optional(),
|
|
14568
|
+
framework_extras: external_exports.record(external_exports.string(), external_exports.unknown()).nullable().optional()
|
|
14569
|
+
}).strict();
|
|
14550
14570
|
var BackendExceptionPayloadSchema = external_exports.object({
|
|
14551
14571
|
name: external_exports.string().min(1),
|
|
14552
14572
|
message: external_exports.string().min(1),
|
|
@@ -14564,9 +14584,7 @@ var BackendExceptionPayloadSchema = external_exports.object({
|
|
|
14564
14584
|
headers: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
14565
14585
|
body: external_exports.unknown().optional()
|
|
14566
14586
|
}),
|
|
14567
|
-
runtime:
|
|
14568
|
-
version: external_exports.string().min(1)
|
|
14569
|
-
}),
|
|
14587
|
+
runtime: BackendRuntimePayloadSchema,
|
|
14570
14588
|
probe_data: InlineProbeDataSchema.optional()
|
|
14571
14589
|
}).strict();
|
|
14572
14590
|
var RequestEventPayloadSchema = external_exports.object({
|
|
@@ -14837,13 +14855,7 @@ var ContextDeploySchema = external_exports.object({
|
|
|
14837
14855
|
deployed_at: external_exports.string().datetime().nullable(),
|
|
14838
14856
|
regression_window: external_exports.boolean().nullable()
|
|
14839
14857
|
});
|
|
14840
|
-
var MemoryStatsSchema =
|
|
14841
|
-
rss: external_exports.number().nonnegative().nullable(),
|
|
14842
|
-
heap_total: external_exports.number().nonnegative().nullable(),
|
|
14843
|
-
heap_used: external_exports.number().nonnegative().nullable(),
|
|
14844
|
-
external: external_exports.number().nonnegative().nullable(),
|
|
14845
|
-
peak: external_exports.number().nonnegative().nullable()
|
|
14846
|
-
});
|
|
14858
|
+
var MemoryStatsSchema = RuntimeMemoryStatsSchema;
|
|
14847
14859
|
var ContextRuntimeSchema = external_exports.object({
|
|
14848
14860
|
version: external_exports.literal(1),
|
|
14849
14861
|
name: external_exports.string().min(1),
|
|
@@ -16221,9 +16233,11 @@ function deriveIncidentReasonFromSourceEventTypes(eventTypes) {
|
|
|
16221
16233
|
return null;
|
|
16222
16234
|
}
|
|
16223
16235
|
|
|
16224
|
-
// ../../packages/auth/src/
|
|
16236
|
+
// ../../packages/auth/src/primitives.ts
|
|
16225
16237
|
var import_argon2 = require("@node-rs/argon2");
|
|
16226
|
-
|
|
16238
|
+
|
|
16239
|
+
// ../../packages/auth/src/web-session-auth.ts
|
|
16240
|
+
var DEFAULT_SESSION_LIFETIME_MS = 1e3 * 60 * 60 * 24 * 7;
|
|
16227
16241
|
var DEFAULT_EMAIL_AUTH_CODE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
16228
16242
|
var DEFAULT_GITHUB_OAUTH_STATE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
16229
16243
|
|
|
@@ -16551,6 +16565,37 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
16551
16565
|
"ALTER TABLE organizations ADD COLUMN IF NOT EXISTS suspended_at timestamptz",
|
|
16552
16566
|
"ALTER TABLE organization_members ADD COLUMN IF NOT EXISTS suspended_at timestamptz"
|
|
16553
16567
|
]
|
|
16568
|
+
}),
|
|
16569
|
+
defineStorageSchemaMigration({
|
|
16570
|
+
id: "202605120001_add_github_device_authorizations",
|
|
16571
|
+
description: "Add persisted GitHub CLI bootstrap state for device-flow login.",
|
|
16572
|
+
statements: [
|
|
16573
|
+
`
|
|
16574
|
+
CREATE TABLE IF NOT EXISTS github_device_authorizations (
|
|
16575
|
+
id uuid PRIMARY KEY,
|
|
16576
|
+
device_code text NOT NULL UNIQUE,
|
|
16577
|
+
user_code text NOT NULL,
|
|
16578
|
+
verification_uri text NOT NULL,
|
|
16579
|
+
interval_seconds integer NOT NULL,
|
|
16580
|
+
expires_at timestamptz NOT NULL,
|
|
16581
|
+
accepted_terms_at timestamptz,
|
|
16582
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
16583
|
+
completed_at timestamptz,
|
|
16584
|
+
claimed_at timestamptz,
|
|
16585
|
+
terminal_error text,
|
|
16586
|
+
user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
16587
|
+
organization_id uuid REFERENCES organizations(id) ON DELETE SET NULL
|
|
16588
|
+
)
|
|
16589
|
+
`,
|
|
16590
|
+
`
|
|
16591
|
+
CREATE INDEX IF NOT EXISTS github_device_authorizations_user_code_idx
|
|
16592
|
+
ON github_device_authorizations (user_code, created_at DESC)
|
|
16593
|
+
`,
|
|
16594
|
+
`
|
|
16595
|
+
CREATE INDEX IF NOT EXISTS github_device_authorizations_expires_at_idx
|
|
16596
|
+
ON github_device_authorizations (expires_at)
|
|
16597
|
+
`
|
|
16598
|
+
]
|
|
16554
16599
|
})
|
|
16555
16600
|
];
|
|
16556
16601
|
|
|
@@ -17289,7 +17334,7 @@ async function countCloudArtifactCache(dependencies) {
|
|
|
17289
17334
|
}
|
|
17290
17335
|
|
|
17291
17336
|
// src/connect-command.ts
|
|
17292
|
-
var
|
|
17337
|
+
var import_promises8 = require("node:fs/promises");
|
|
17293
17338
|
var import_node_path9 = require("node:path");
|
|
17294
17339
|
|
|
17295
17340
|
// ../../packages/project-management-client/src/index.ts
|
|
@@ -17732,7 +17777,8 @@ function createAlertApi(client) {
|
|
|
17732
17777
|
const body = {
|
|
17733
17778
|
project_id: input.projectId,
|
|
17734
17779
|
channel: input.channel,
|
|
17735
|
-
condition_type: input.conditionType
|
|
17780
|
+
condition_type: input.conditionType,
|
|
17781
|
+
config: input.config
|
|
17736
17782
|
};
|
|
17737
17783
|
if (input.serviceId !== void 0) {
|
|
17738
17784
|
body.service_id = input.serviceId;
|
|
@@ -17740,9 +17786,6 @@ function createAlertApi(client) {
|
|
|
17740
17786
|
if (input.severityMin !== void 0) {
|
|
17741
17787
|
body.severity_min = input.severityMin;
|
|
17742
17788
|
}
|
|
17743
|
-
if (input.config !== void 0) {
|
|
17744
|
-
body.config = input.config;
|
|
17745
|
-
}
|
|
17746
17789
|
if (input.isEnabled !== void 0) {
|
|
17747
17790
|
body.is_enabled = input.isEnabled;
|
|
17748
17791
|
}
|
|
@@ -18979,6 +19022,531 @@ async function readConnectionConfig(rootDirectory, readFile) {
|
|
|
18979
19022
|
return parsed.data;
|
|
18980
19023
|
}
|
|
18981
19024
|
|
|
19025
|
+
// src/interactive-auth.ts
|
|
19026
|
+
var import_node_process = require("node:process");
|
|
19027
|
+
var import_promises7 = require("node:readline/promises");
|
|
19028
|
+
function isInteractiveTerminal() {
|
|
19029
|
+
return import_node_process.stdin.isTTY === true && import_node_process.stdout.isTTY === true;
|
|
19030
|
+
}
|
|
19031
|
+
async function promptForInteractiveLoginSelection() {
|
|
19032
|
+
const readlineInterface = (0, import_promises7.createInterface)({
|
|
19033
|
+
input: import_node_process.stdin,
|
|
19034
|
+
output: import_node_process.stdout
|
|
19035
|
+
});
|
|
19036
|
+
try {
|
|
19037
|
+
import_node_process.stdout.write(
|
|
19038
|
+
[
|
|
19039
|
+
"Choose an authentication method:",
|
|
19040
|
+
"1. GitHub (auto: use gh if available, otherwise device flow)",
|
|
19041
|
+
"2. GitHub device flow",
|
|
19042
|
+
"3. Existing member token",
|
|
19043
|
+
"4. Cancel"
|
|
19044
|
+
].join("\n") + "\n"
|
|
19045
|
+
);
|
|
19046
|
+
for (; ; ) {
|
|
19047
|
+
const selection = (await readlineInterface.question("Selection [1-4]: ")).trim();
|
|
19048
|
+
if (selection === "1") {
|
|
19049
|
+
return { kind: "github" };
|
|
19050
|
+
}
|
|
19051
|
+
if (selection === "2") {
|
|
19052
|
+
return { kind: "github-device" };
|
|
19053
|
+
}
|
|
19054
|
+
if (selection === "3") {
|
|
19055
|
+
const bearerToken = (await readlineInterface.question("Paste your member token: ")).trim();
|
|
19056
|
+
if (bearerToken.length > 0) {
|
|
19057
|
+
return {
|
|
19058
|
+
kind: "member-token",
|
|
19059
|
+
bearerToken
|
|
19060
|
+
};
|
|
19061
|
+
}
|
|
19062
|
+
import_node_process.stdout.write("Member token cannot be empty.\n");
|
|
19063
|
+
continue;
|
|
19064
|
+
}
|
|
19065
|
+
if (selection === "4") {
|
|
19066
|
+
return { kind: "cancel" };
|
|
19067
|
+
}
|
|
19068
|
+
import_node_process.stdout.write("Enter 1, 2, 3, or 4.\n");
|
|
19069
|
+
}
|
|
19070
|
+
} finally {
|
|
19071
|
+
readlineInterface.close();
|
|
19072
|
+
}
|
|
19073
|
+
}
|
|
19074
|
+
|
|
19075
|
+
// src/login-command.ts
|
|
19076
|
+
var import_node_child_process = require("node:child_process");
|
|
19077
|
+
var import_node_util = require("node:util");
|
|
19078
|
+
var execFile = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
19079
|
+
var DEFAULT_BASE_URL = "https://api.debugbundle.com";
|
|
19080
|
+
var DEFAULT_GITHUB_BOOTSTRAP_LABEL = "GitHub bootstrap";
|
|
19081
|
+
var MIN_DEVICE_POLL_INTERVAL_SECONDS = 7;
|
|
19082
|
+
var LoginCommandInputSchema = external_exports.object({
|
|
19083
|
+
bearerToken: external_exports.string().trim().min(1).optional(),
|
|
19084
|
+
baseUrl: external_exports.string().url().default(DEFAULT_BASE_URL),
|
|
19085
|
+
github: external_exports.boolean().optional(),
|
|
19086
|
+
githubCli: external_exports.boolean().optional(),
|
|
19087
|
+
githubDevice: external_exports.boolean().optional(),
|
|
19088
|
+
label: external_exports.string().trim().min(1).max(120).default(DEFAULT_GITHUB_BOOTSTRAP_LABEL)
|
|
19089
|
+
}).superRefine((value, context) => {
|
|
19090
|
+
const githubModeCount = [value.github, value.githubCli, value.githubDevice].filter((flag) => flag === true).length;
|
|
19091
|
+
if (githubModeCount > 1) {
|
|
19092
|
+
context.addIssue({
|
|
19093
|
+
code: external_exports.ZodIssueCode.custom,
|
|
19094
|
+
message: "github_mode_conflict"
|
|
19095
|
+
});
|
|
19096
|
+
}
|
|
19097
|
+
if (value.bearerToken !== void 0 && githubModeCount > 0) {
|
|
19098
|
+
context.addIssue({
|
|
19099
|
+
code: external_exports.ZodIssueCode.custom,
|
|
19100
|
+
message: "login_mode_conflict"
|
|
19101
|
+
});
|
|
19102
|
+
}
|
|
19103
|
+
if (value.bearerToken === void 0 && githubModeCount === 0) {
|
|
19104
|
+
context.addIssue({
|
|
19105
|
+
code: external_exports.ZodIssueCode.custom,
|
|
19106
|
+
message: "login_mode_missing"
|
|
19107
|
+
});
|
|
19108
|
+
}
|
|
19109
|
+
});
|
|
19110
|
+
var ApiErrorResponseSchema9 = external_exports.object({
|
|
19111
|
+
error: external_exports.string()
|
|
19112
|
+
}).strict();
|
|
19113
|
+
var DeviceStartResponseSchema = external_exports.object({
|
|
19114
|
+
request_id: external_exports.string().uuid(),
|
|
19115
|
+
user_code: external_exports.string().min(1),
|
|
19116
|
+
verification_uri: external_exports.string().url(),
|
|
19117
|
+
interval_seconds: external_exports.number().int().positive(),
|
|
19118
|
+
expires_at: external_exports.string().datetime()
|
|
19119
|
+
}).strict();
|
|
19120
|
+
var DevicePollResponseSchema = external_exports.discriminatedUnion("status", [
|
|
19121
|
+
external_exports.object({
|
|
19122
|
+
status: external_exports.literal("pending"),
|
|
19123
|
+
interval_seconds: external_exports.number().int().positive(),
|
|
19124
|
+
expires_at: external_exports.string().datetime()
|
|
19125
|
+
}).strict(),
|
|
19126
|
+
external_exports.object({
|
|
19127
|
+
status: external_exports.enum(["approved", "claimed"]),
|
|
19128
|
+
expires_at: external_exports.string().datetime()
|
|
19129
|
+
}).strict(),
|
|
19130
|
+
external_exports.object({
|
|
19131
|
+
status: external_exports.enum(["denied", "expired", "rejected"]),
|
|
19132
|
+
reason: external_exports.string(),
|
|
19133
|
+
expires_at: external_exports.string().datetime()
|
|
19134
|
+
}).strict()
|
|
19135
|
+
]);
|
|
19136
|
+
var MemberTokenResponseSchema = external_exports.object({
|
|
19137
|
+
token: external_exports.object({
|
|
19138
|
+
token_id: external_exports.string(),
|
|
19139
|
+
user_id: external_exports.string(),
|
|
19140
|
+
organization_id: external_exports.string(),
|
|
19141
|
+
label: external_exports.string(),
|
|
19142
|
+
created_at: external_exports.string(),
|
|
19143
|
+
last_used_at: external_exports.string().nullable(),
|
|
19144
|
+
revoked_at: external_exports.string().nullable(),
|
|
19145
|
+
expires_at: external_exports.string().nullable(),
|
|
19146
|
+
plaintext: external_exports.string()
|
|
19147
|
+
}).strict()
|
|
19148
|
+
}).strict();
|
|
19149
|
+
var LoginApiError = class extends Error {
|
|
19150
|
+
status;
|
|
19151
|
+
code;
|
|
19152
|
+
constructor(status, code) {
|
|
19153
|
+
super(`login_api_error: ${status}:${code}`);
|
|
19154
|
+
this.status = status;
|
|
19155
|
+
this.code = code;
|
|
19156
|
+
}
|
|
19157
|
+
};
|
|
19158
|
+
function normalizeBaseUrl2(baseUrl) {
|
|
19159
|
+
return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
19160
|
+
}
|
|
19161
|
+
function formatLoginOutput(authState, authFilePath) {
|
|
19162
|
+
return [
|
|
19163
|
+
"Authenticated: yes",
|
|
19164
|
+
`Base URL: ${authState.base_url}`,
|
|
19165
|
+
`Auth File: ${authFilePath}`,
|
|
19166
|
+
`Token: ${buildTokenPreview(authState.bearer_token)}`
|
|
19167
|
+
].join("\n");
|
|
19168
|
+
}
|
|
19169
|
+
function validateMemberToken(token) {
|
|
19170
|
+
return token.startsWith("dbundle_mem_");
|
|
19171
|
+
}
|
|
19172
|
+
function resolveLoginMode(input) {
|
|
19173
|
+
if (input.bearerToken !== void 0) {
|
|
19174
|
+
return "token";
|
|
19175
|
+
}
|
|
19176
|
+
if (input.githubCli === true) {
|
|
19177
|
+
return "github-cli";
|
|
19178
|
+
}
|
|
19179
|
+
if (input.githubDevice === true) {
|
|
19180
|
+
return "github-device";
|
|
19181
|
+
}
|
|
19182
|
+
return "github";
|
|
19183
|
+
}
|
|
19184
|
+
function hasExplicitLoginMode(input) {
|
|
19185
|
+
return input.bearerToken !== void 0 || input.github === true || input.githubCli === true || input.githubDevice === true;
|
|
19186
|
+
}
|
|
19187
|
+
async function maybePromptForLoginInput(input, dependencies) {
|
|
19188
|
+
if (hasExplicitLoginMode(input) || input.json === true) {
|
|
19189
|
+
return input;
|
|
19190
|
+
}
|
|
19191
|
+
const interactive = (dependencies?.isInteractiveTerminal ?? isInteractiveTerminal)();
|
|
19192
|
+
if (!interactive) {
|
|
19193
|
+
return input;
|
|
19194
|
+
}
|
|
19195
|
+
const selection = await (dependencies?.promptForInteractiveLogin ?? promptForInteractiveLoginSelection)();
|
|
19196
|
+
if (selection.kind === "cancel") {
|
|
19197
|
+
return {
|
|
19198
|
+
exitCode: 4,
|
|
19199
|
+
output: "Authentication cancelled."
|
|
19200
|
+
};
|
|
19201
|
+
}
|
|
19202
|
+
if (selection.kind === "member-token") {
|
|
19203
|
+
return {
|
|
19204
|
+
...input,
|
|
19205
|
+
bearerToken: selection.bearerToken
|
|
19206
|
+
};
|
|
19207
|
+
}
|
|
19208
|
+
if (selection.kind === "github-device") {
|
|
19209
|
+
return {
|
|
19210
|
+
...input,
|
|
19211
|
+
githubDevice: true
|
|
19212
|
+
};
|
|
19213
|
+
}
|
|
19214
|
+
return {
|
|
19215
|
+
...input,
|
|
19216
|
+
github: true
|
|
19217
|
+
};
|
|
19218
|
+
}
|
|
19219
|
+
function mapInputValidationError(parsedInput) {
|
|
19220
|
+
if (parsedInput.error.issues.some((issue) => issue.message === "github_mode_conflict")) {
|
|
19221
|
+
return "Choose only one of --github, --github-cli, or --github-device.";
|
|
19222
|
+
}
|
|
19223
|
+
if (parsedInput.error.issues.some((issue) => issue.message === "login_mode_conflict")) {
|
|
19224
|
+
return "Use either a member token or a GitHub login mode, not both.";
|
|
19225
|
+
}
|
|
19226
|
+
if (parsedInput.error.issues.some((issue) => issue.message === "login_mode_missing")) {
|
|
19227
|
+
return "Provide either a member token or one of --github, --github-cli, or --github-device.";
|
|
19228
|
+
}
|
|
19229
|
+
return "Invalid login options.";
|
|
19230
|
+
}
|
|
19231
|
+
function mapApiErrorToMessage(error) {
|
|
19232
|
+
switch (error.code) {
|
|
19233
|
+
case "auth_not_configured":
|
|
19234
|
+
return "GitHub login is not configured on this DebugBundle API.";
|
|
19235
|
+
case "github_device_flow_disabled":
|
|
19236
|
+
return "GitHub device flow is not enabled for this DebugBundle API.";
|
|
19237
|
+
case "github_oauth_unavailable":
|
|
19238
|
+
return "GitHub OAuth is temporarily unavailable.";
|
|
19239
|
+
case "invalid_github_token":
|
|
19240
|
+
return "The local GitHub CLI token was rejected by DebugBundle.";
|
|
19241
|
+
case "github_device_request_not_found":
|
|
19242
|
+
return "GitHub device authorization request was not found.";
|
|
19243
|
+
case "github_device_auth_pending":
|
|
19244
|
+
return "GitHub device authorization has not completed yet.";
|
|
19245
|
+
case "github_device_auth_expired":
|
|
19246
|
+
return "GitHub device authorization expired before it could be claimed.";
|
|
19247
|
+
case "github_device_auth_claimed":
|
|
19248
|
+
return "GitHub device authorization was already claimed.";
|
|
19249
|
+
case "github_device_auth_rejected":
|
|
19250
|
+
return "GitHub device authorization was rejected.";
|
|
19251
|
+
case "github_email_unavailable":
|
|
19252
|
+
return "GitHub did not provide a verified primary email address.";
|
|
19253
|
+
case "account_signup_disabled":
|
|
19254
|
+
return "This DebugBundle workspace does not allow new account signups for this GitHub identity.";
|
|
19255
|
+
case "account_suspended":
|
|
19256
|
+
return "This DebugBundle account is suspended.";
|
|
19257
|
+
case "rate_limited":
|
|
19258
|
+
return "GitHub login was rate limited. Please wait and try again.";
|
|
19259
|
+
default:
|
|
19260
|
+
return `GitHub login failed: ${error.code}`;
|
|
19261
|
+
}
|
|
19262
|
+
}
|
|
19263
|
+
async function parseResponseBody2(response) {
|
|
19264
|
+
const rawBody = await response.text();
|
|
19265
|
+
if (rawBody.length === 0) {
|
|
19266
|
+
return null;
|
|
19267
|
+
}
|
|
19268
|
+
try {
|
|
19269
|
+
return JSON.parse(rawBody);
|
|
19270
|
+
} catch {
|
|
19271
|
+
return rawBody;
|
|
19272
|
+
}
|
|
19273
|
+
}
|
|
19274
|
+
async function requestJson(input, dependencies) {
|
|
19275
|
+
const fetchImpl = dependencies?.fetchImpl ?? fetch;
|
|
19276
|
+
const response = await fetchImpl(`${normalizeBaseUrl2(input.baseUrl)}${input.path}`, {
|
|
19277
|
+
method: input.method,
|
|
19278
|
+
headers: {
|
|
19279
|
+
accept: "application/json",
|
|
19280
|
+
"content-type": "application/json"
|
|
19281
|
+
},
|
|
19282
|
+
body: JSON.stringify(input.body)
|
|
19283
|
+
});
|
|
19284
|
+
const body = await parseResponseBody2(response);
|
|
19285
|
+
if (response.status < 200 || response.status >= 300) {
|
|
19286
|
+
const parsedError = ApiErrorResponseSchema9.safeParse(body);
|
|
19287
|
+
throw new LoginApiError(response.status, parsedError.success ? parsedError.data.error : "unknown_error");
|
|
19288
|
+
}
|
|
19289
|
+
return body;
|
|
19290
|
+
}
|
|
19291
|
+
async function readGitHubAccessTokenFromGh() {
|
|
19292
|
+
try {
|
|
19293
|
+
const result = await execFile("gh", ["auth", "token"]);
|
|
19294
|
+
const token = result.stdout.trim();
|
|
19295
|
+
return token.length > 0 ? token : null;
|
|
19296
|
+
} catch {
|
|
19297
|
+
return null;
|
|
19298
|
+
}
|
|
19299
|
+
}
|
|
19300
|
+
async function exchangeGitHubToken(input, dependencies) {
|
|
19301
|
+
const body = await requestJson(
|
|
19302
|
+
{
|
|
19303
|
+
baseUrl: input.baseUrl,
|
|
19304
|
+
method: "POST",
|
|
19305
|
+
path: "/v1/auth/github/token/exchange",
|
|
19306
|
+
body: {
|
|
19307
|
+
github_access_token: input.githubAccessToken,
|
|
19308
|
+
label: input.label,
|
|
19309
|
+
accepted_terms: true
|
|
19310
|
+
}
|
|
19311
|
+
},
|
|
19312
|
+
dependencies
|
|
19313
|
+
);
|
|
19314
|
+
return MemberTokenResponseSchema.parse(body);
|
|
19315
|
+
}
|
|
19316
|
+
async function startGitHubDeviceFlow(input, dependencies) {
|
|
19317
|
+
const body = await requestJson(
|
|
19318
|
+
{
|
|
19319
|
+
baseUrl: input.baseUrl,
|
|
19320
|
+
method: "POST",
|
|
19321
|
+
path: "/v1/auth/github/device/start",
|
|
19322
|
+
body: {
|
|
19323
|
+
accepted_terms: true
|
|
19324
|
+
}
|
|
19325
|
+
},
|
|
19326
|
+
dependencies
|
|
19327
|
+
);
|
|
19328
|
+
return DeviceStartResponseSchema.parse(body);
|
|
19329
|
+
}
|
|
19330
|
+
async function pollGitHubDeviceFlow(input, dependencies) {
|
|
19331
|
+
const body = await requestJson(
|
|
19332
|
+
{
|
|
19333
|
+
baseUrl: input.baseUrl,
|
|
19334
|
+
method: "POST",
|
|
19335
|
+
path: "/v1/auth/github/device/poll",
|
|
19336
|
+
body: {
|
|
19337
|
+
request_id: input.requestId
|
|
19338
|
+
}
|
|
19339
|
+
},
|
|
19340
|
+
dependencies
|
|
19341
|
+
);
|
|
19342
|
+
return DevicePollResponseSchema.parse(body);
|
|
19343
|
+
}
|
|
19344
|
+
async function claimGitHubDeviceFlow(input, dependencies) {
|
|
19345
|
+
const body = await requestJson(
|
|
19346
|
+
{
|
|
19347
|
+
baseUrl: input.baseUrl,
|
|
19348
|
+
method: "POST",
|
|
19349
|
+
path: "/v1/auth/github/device/claim",
|
|
19350
|
+
body: {
|
|
19351
|
+
request_id: input.requestId,
|
|
19352
|
+
label: input.label
|
|
19353
|
+
}
|
|
19354
|
+
},
|
|
19355
|
+
dependencies
|
|
19356
|
+
);
|
|
19357
|
+
return MemberTokenResponseSchema.parse(body);
|
|
19358
|
+
}
|
|
19359
|
+
function formatPersistedSuccess(input, dependencies) {
|
|
19360
|
+
const authState = {
|
|
19361
|
+
bearer_token: input.bearerToken,
|
|
19362
|
+
base_url: input.baseUrl
|
|
19363
|
+
};
|
|
19364
|
+
return dependencies.writeAuthState({
|
|
19365
|
+
...input.authFilePath === void 0 ? {} : { authFilePath: input.authFilePath },
|
|
19366
|
+
authState
|
|
19367
|
+
}).then((persistedPath) => {
|
|
19368
|
+
const authFilePath = persistedPath ?? input.authFilePath ?? "";
|
|
19369
|
+
const payload = {
|
|
19370
|
+
authenticated: true,
|
|
19371
|
+
auth: {
|
|
19372
|
+
base_url: authState.base_url,
|
|
19373
|
+
token_preview: buildTokenPreview(authState.bearer_token)
|
|
19374
|
+
},
|
|
19375
|
+
auth_file_path: authFilePath
|
|
19376
|
+
};
|
|
19377
|
+
return {
|
|
19378
|
+
exitCode: 0,
|
|
19379
|
+
output: input.json ? JSON.stringify(payload) : formatLoginOutput(authState, authFilePath)
|
|
19380
|
+
};
|
|
19381
|
+
});
|
|
19382
|
+
}
|
|
19383
|
+
function buildProgressReporter(dependency) {
|
|
19384
|
+
if (dependency !== void 0) {
|
|
19385
|
+
return dependency;
|
|
19386
|
+
}
|
|
19387
|
+
return (text) => {
|
|
19388
|
+
process.stderr.write(`${text}
|
|
19389
|
+
`);
|
|
19390
|
+
};
|
|
19391
|
+
}
|
|
19392
|
+
async function loginCommand(input, dependencies) {
|
|
19393
|
+
const promptedInput = await maybePromptForLoginInput(input, dependencies);
|
|
19394
|
+
if ("exitCode" in promptedInput) {
|
|
19395
|
+
return promptedInput;
|
|
19396
|
+
}
|
|
19397
|
+
const parsedInput = LoginCommandInputSchema.safeParse({
|
|
19398
|
+
bearerToken: promptedInput.bearerToken,
|
|
19399
|
+
baseUrl: promptedInput.baseUrl ?? DEFAULT_BASE_URL,
|
|
19400
|
+
github: promptedInput.github,
|
|
19401
|
+
githubCli: promptedInput.githubCli,
|
|
19402
|
+
githubDevice: promptedInput.githubDevice,
|
|
19403
|
+
label: promptedInput.label ?? DEFAULT_GITHUB_BOOTSTRAP_LABEL
|
|
19404
|
+
});
|
|
19405
|
+
if (!parsedInput.success) {
|
|
19406
|
+
return {
|
|
19407
|
+
exitCode: 4,
|
|
19408
|
+
output: mapInputValidationError(parsedInput)
|
|
19409
|
+
};
|
|
19410
|
+
}
|
|
19411
|
+
const normalizedInput = parsedInput.data;
|
|
19412
|
+
const writeAuthState = dependencies?.writeAuthState ?? persistCliAuthState;
|
|
19413
|
+
try {
|
|
19414
|
+
if (resolveLoginMode(normalizedInput) === "token") {
|
|
19415
|
+
if (!validateMemberToken(normalizedInput.bearerToken)) {
|
|
19416
|
+
return {
|
|
19417
|
+
exitCode: 4,
|
|
19418
|
+
output: "Invalid member token."
|
|
19419
|
+
};
|
|
19420
|
+
}
|
|
19421
|
+
return await formatPersistedSuccess(
|
|
19422
|
+
{
|
|
19423
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19424
|
+
bearerToken: normalizedInput.bearerToken,
|
|
19425
|
+
...promptedInput.json === void 0 ? {} : { json: promptedInput.json },
|
|
19426
|
+
...promptedInput.authFilePath === void 0 ? {} : { authFilePath: promptedInput.authFilePath }
|
|
19427
|
+
},
|
|
19428
|
+
{ writeAuthState }
|
|
19429
|
+
);
|
|
19430
|
+
}
|
|
19431
|
+
const readGitHubAccessToken = dependencies?.readGitHubAccessToken ?? readGitHubAccessTokenFromGh;
|
|
19432
|
+
const sleep = dependencies?.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
19433
|
+
const reportProgress = buildProgressReporter(dependencies?.reportProgress);
|
|
19434
|
+
const loginMode = resolveLoginMode(normalizedInput);
|
|
19435
|
+
if (loginMode !== "github-device") {
|
|
19436
|
+
const githubAccessToken = await readGitHubAccessToken();
|
|
19437
|
+
if (githubAccessToken !== null) {
|
|
19438
|
+
reportProgress("Using existing GitHub CLI authentication.");
|
|
19439
|
+
try {
|
|
19440
|
+
const exchanged = await exchangeGitHubToken(
|
|
19441
|
+
{
|
|
19442
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19443
|
+
githubAccessToken,
|
|
19444
|
+
label: normalizedInput.label
|
|
19445
|
+
},
|
|
19446
|
+
dependencies
|
|
19447
|
+
);
|
|
19448
|
+
return await formatPersistedSuccess(
|
|
19449
|
+
{
|
|
19450
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19451
|
+
bearerToken: exchanged.token.plaintext,
|
|
19452
|
+
...promptedInput.json === void 0 ? {} : { json: promptedInput.json },
|
|
19453
|
+
...promptedInput.authFilePath === void 0 ? {} : { authFilePath: promptedInput.authFilePath }
|
|
19454
|
+
},
|
|
19455
|
+
{ writeAuthState }
|
|
19456
|
+
);
|
|
19457
|
+
} catch (error) {
|
|
19458
|
+
if (!(error instanceof LoginApiError)) {
|
|
19459
|
+
throw error;
|
|
19460
|
+
}
|
|
19461
|
+
if (loginMode === "github-cli" || error.code !== "invalid_github_token") {
|
|
19462
|
+
return {
|
|
19463
|
+
exitCode: error.status === 401 || error.status === 403 ? 4 : 1,
|
|
19464
|
+
output: mapApiErrorToMessage(error)
|
|
19465
|
+
};
|
|
19466
|
+
}
|
|
19467
|
+
reportProgress("The local GitHub CLI token was not accepted. Falling back to device flow.");
|
|
19468
|
+
}
|
|
19469
|
+
} else if (loginMode === "github-cli") {
|
|
19470
|
+
return {
|
|
19471
|
+
exitCode: 4,
|
|
19472
|
+
output: "GitHub CLI is not authenticated on this machine."
|
|
19473
|
+
};
|
|
19474
|
+
} else {
|
|
19475
|
+
reportProgress("GitHub CLI is not authenticated. Falling back to device flow.");
|
|
19476
|
+
}
|
|
19477
|
+
}
|
|
19478
|
+
const started = await startGitHubDeviceFlow(
|
|
19479
|
+
{
|
|
19480
|
+
baseUrl: normalizedInput.baseUrl
|
|
19481
|
+
},
|
|
19482
|
+
dependencies
|
|
19483
|
+
);
|
|
19484
|
+
reportProgress(`Open ${started.verification_uri} and enter code ${started.user_code}.`);
|
|
19485
|
+
reportProgress("Waiting for GitHub approval...");
|
|
19486
|
+
let intervalSeconds = Math.max(started.interval_seconds, MIN_DEVICE_POLL_INTERVAL_SECONDS);
|
|
19487
|
+
for (; ; ) {
|
|
19488
|
+
await sleep(intervalSeconds * 1e3);
|
|
19489
|
+
const polled = await pollGitHubDeviceFlow(
|
|
19490
|
+
{
|
|
19491
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19492
|
+
requestId: started.request_id
|
|
19493
|
+
},
|
|
19494
|
+
dependencies
|
|
19495
|
+
);
|
|
19496
|
+
if (polled.status === "pending") {
|
|
19497
|
+
intervalSeconds = Math.max(polled.interval_seconds, MIN_DEVICE_POLL_INTERVAL_SECONDS);
|
|
19498
|
+
continue;
|
|
19499
|
+
}
|
|
19500
|
+
if (polled.status === "approved") {
|
|
19501
|
+
const claimed = await claimGitHubDeviceFlow(
|
|
19502
|
+
{
|
|
19503
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19504
|
+
requestId: started.request_id,
|
|
19505
|
+
label: normalizedInput.label
|
|
19506
|
+
},
|
|
19507
|
+
dependencies
|
|
19508
|
+
);
|
|
19509
|
+
return await formatPersistedSuccess(
|
|
19510
|
+
{
|
|
19511
|
+
baseUrl: normalizedInput.baseUrl,
|
|
19512
|
+
bearerToken: claimed.token.plaintext,
|
|
19513
|
+
...promptedInput.json === void 0 ? {} : { json: promptedInput.json },
|
|
19514
|
+
...promptedInput.authFilePath === void 0 ? {} : { authFilePath: promptedInput.authFilePath }
|
|
19515
|
+
},
|
|
19516
|
+
{ writeAuthState }
|
|
19517
|
+
);
|
|
19518
|
+
}
|
|
19519
|
+
if (polled.status === "claimed") {
|
|
19520
|
+
return {
|
|
19521
|
+
exitCode: 4,
|
|
19522
|
+
output: "GitHub device authorization was already claimed."
|
|
19523
|
+
};
|
|
19524
|
+
}
|
|
19525
|
+
if (polled.status === "denied" || polled.status === "expired" || polled.status === "rejected") {
|
|
19526
|
+
return {
|
|
19527
|
+
exitCode: 4,
|
|
19528
|
+
output: polled.status === "denied" ? "GitHub device authorization was denied." : polled.status === "expired" ? "GitHub device authorization expired." : `GitHub device authorization was rejected: ${polled.reason}`
|
|
19529
|
+
};
|
|
19530
|
+
}
|
|
19531
|
+
return {
|
|
19532
|
+
exitCode: 1,
|
|
19533
|
+
output: "GitHub device authorization returned an unexpected status."
|
|
19534
|
+
};
|
|
19535
|
+
}
|
|
19536
|
+
} catch (error) {
|
|
19537
|
+
if (error instanceof LoginApiError) {
|
|
19538
|
+
return {
|
|
19539
|
+
exitCode: error.status === 400 || error.status === 401 || error.status === 403 || error.status === 409 ? 4 : 1,
|
|
19540
|
+
output: mapApiErrorToMessage(error)
|
|
19541
|
+
};
|
|
19542
|
+
}
|
|
19543
|
+
return {
|
|
19544
|
+
exitCode: 1,
|
|
19545
|
+
output: error instanceof Error ? error.message : String(error)
|
|
19546
|
+
};
|
|
19547
|
+
}
|
|
19548
|
+
}
|
|
19549
|
+
|
|
18982
19550
|
// src/connect-command.ts
|
|
18983
19551
|
var ProfileNameSchema = external_exports.object({
|
|
18984
19552
|
project: external_exports.object({
|
|
@@ -19068,9 +19636,9 @@ function buildValidationFailureResult(input) {
|
|
|
19068
19636
|
}
|
|
19069
19637
|
async function connectCommand(input, dependencies = {}) {
|
|
19070
19638
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
19071
|
-
const readFile = dependencies.readFile ?? ((path) => (0,
|
|
19072
|
-
const stat = dependencies.stat ??
|
|
19073
|
-
const writeFile = dependencies.writeFile ??
|
|
19639
|
+
const readFile = dependencies.readFile ?? ((path) => (0, import_promises8.readFile)(path, "utf8"));
|
|
19640
|
+
const stat = dependencies.stat ?? import_promises8.stat;
|
|
19641
|
+
const writeFile = dependencies.writeFile ?? import_promises8.writeFile;
|
|
19074
19642
|
const readAuthState = dependencies.readAuthState ?? ((authInput) => readCliAuthState(authInput));
|
|
19075
19643
|
const createHttpClient = dependencies.createHttpClient ?? ((clientInput) => {
|
|
19076
19644
|
const httpClientDependencies = {};
|
|
@@ -19081,6 +19649,7 @@ async function connectCommand(input, dependencies = {}) {
|
|
|
19081
19649
|
});
|
|
19082
19650
|
const createProjectApi = dependencies.createProjectManagementApi ?? createProjectManagementApi;
|
|
19083
19651
|
const createTokenApi = dependencies.createTokenManagementApi ?? createTokenManagementApi;
|
|
19652
|
+
const loginCommand2 = dependencies.loginCommand ?? loginCommand;
|
|
19084
19653
|
const rootDirectory = cwd();
|
|
19085
19654
|
const initialChecks = [];
|
|
19086
19655
|
const profileValidation = await readValidatedProfileName(rootDirectory, { readFile, stat });
|
|
@@ -19137,7 +19706,22 @@ async function connectCommand(input, dependencies = {}) {
|
|
|
19137
19706
|
message: `Found ${CONNECTION_FILE_PATH}`
|
|
19138
19707
|
});
|
|
19139
19708
|
try {
|
|
19140
|
-
|
|
19709
|
+
let authState;
|
|
19710
|
+
try {
|
|
19711
|
+
authState = await readAuthState({ ...input.authFilePath === void 0 ? {} : { authFilePath: input.authFilePath } });
|
|
19712
|
+
} catch (error) {
|
|
19713
|
+
const shouldAttemptInteractiveLogin = error instanceof CliAuthStateError && error.code === "auth_state_missing" && input.json !== true && (dependencies.isInteractiveTerminal ?? isInteractiveTerminal)();
|
|
19714
|
+
if (!shouldAttemptInteractiveLogin) {
|
|
19715
|
+
throw error;
|
|
19716
|
+
}
|
|
19717
|
+
const loginResult = await loginCommand2({
|
|
19718
|
+
...input.authFilePath === void 0 ? {} : { authFilePath: input.authFilePath }
|
|
19719
|
+
});
|
|
19720
|
+
if (loginResult.exitCode !== 0) {
|
|
19721
|
+
return loginResult;
|
|
19722
|
+
}
|
|
19723
|
+
authState = await readAuthState({ ...input.authFilePath === void 0 ? {} : { authFilePath: input.authFilePath } });
|
|
19724
|
+
}
|
|
19141
19725
|
const httpClient = createHttpClient({ baseUrl: authState.base_url });
|
|
19142
19726
|
const projectApi = createProjectApi(httpClient);
|
|
19143
19727
|
const tokenApi = createTokenApi(httpClient);
|
|
@@ -19241,7 +19825,7 @@ async function connectCommand(input, dependencies = {}) {
|
|
|
19241
19825
|
message
|
|
19242
19826
|
}
|
|
19243
19827
|
], [
|
|
19244
|
-
exitCode === 2 ? "Run debugbundle login before connecting the project to cloud." : "Resolve the cloud API error and retry debugbundle connect."
|
|
19828
|
+
exitCode === 2 ? "Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> before connecting the project to cloud." : "Resolve the cloud API error and retry debugbundle connect."
|
|
19245
19829
|
]) : `DebugBundle connect failed.
|
|
19246
19830
|
- ${message}`
|
|
19247
19831
|
};
|
|
@@ -19249,7 +19833,7 @@ async function connectCommand(input, dependencies = {}) {
|
|
|
19249
19833
|
}
|
|
19250
19834
|
|
|
19251
19835
|
// src/doctor-command.ts
|
|
19252
|
-
var
|
|
19836
|
+
var import_promises9 = require("node:fs/promises");
|
|
19253
19837
|
var import_node_path10 = require("node:path");
|
|
19254
19838
|
var ProfileSchema2 = external_exports.object({
|
|
19255
19839
|
debugbundle: external_exports.object({
|
|
@@ -19269,7 +19853,7 @@ var RELAY_SPOOL_DELIVERED_MARKER_SUFFIX2 = ".delivered";
|
|
|
19269
19853
|
var RELAY_SPOOL_EVENT_SUFFIX = ".events.json";
|
|
19270
19854
|
var SUGGESTED_ACTIONS = [
|
|
19271
19855
|
"Run debugbundle setup if local scaffold files are missing.",
|
|
19272
|
-
"Run debugbundle login to create ~/.debugbundle/auth.json.",
|
|
19856
|
+
"Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> to create ~/.debugbundle/auth.json.",
|
|
19273
19857
|
"Review .debugbundle/profile.json when architecture changes or the profile becomes stale."
|
|
19274
19858
|
];
|
|
19275
19859
|
async function pathExists3(path, stat) {
|
|
@@ -19471,7 +20055,7 @@ async function loadConnection(rootDirectory, dependencies) {
|
|
|
19471
20055
|
};
|
|
19472
20056
|
}
|
|
19473
20057
|
}
|
|
19474
|
-
function
|
|
20058
|
+
function normalizeBaseUrl3(baseUrl) {
|
|
19475
20059
|
return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
19476
20060
|
}
|
|
19477
20061
|
function buildProjectModeCheck(connection) {
|
|
@@ -19571,7 +20155,7 @@ async function buildAuthCheck(input, readAuthStateImpl) {
|
|
|
19571
20155
|
};
|
|
19572
20156
|
}
|
|
19573
20157
|
}
|
|
19574
|
-
async function
|
|
20158
|
+
async function parseResponseBody3(response) {
|
|
19575
20159
|
const rawBody = await response.text();
|
|
19576
20160
|
if (rawBody.length === 0) {
|
|
19577
20161
|
return null;
|
|
@@ -19586,8 +20170,8 @@ async function buildConnectedApiCheck(input) {
|
|
|
19586
20170
|
if (input.connection === null || input.connection.mode !== "connected") {
|
|
19587
20171
|
return null;
|
|
19588
20172
|
}
|
|
19589
|
-
const connectionBaseUrl = input.connection.cloud_base_url === null ? null :
|
|
19590
|
-
const authBaseUrl = input.authState === null ? null :
|
|
20173
|
+
const connectionBaseUrl = input.connection.cloud_base_url === null ? null : normalizeBaseUrl3(input.connection.cloud_base_url);
|
|
20174
|
+
const authBaseUrl = input.authState === null ? null : normalizeBaseUrl3(input.authState.base_url);
|
|
19591
20175
|
const baseUrl = authBaseUrl ?? connectionBaseUrl;
|
|
19592
20176
|
if (baseUrl === null) {
|
|
19593
20177
|
return {
|
|
@@ -19611,7 +20195,7 @@ async function buildConnectedApiCheck(input) {
|
|
|
19611
20195
|
message: `Connected API ${baseUrl} could not be reached: ${error instanceof Error ? error.message : String(error)}`
|
|
19612
20196
|
};
|
|
19613
20197
|
}
|
|
19614
|
-
const parsedHealthBody = await
|
|
20198
|
+
const parsedHealthBody = await parseResponseBody3(healthResponse);
|
|
19615
20199
|
if (healthResponse.status !== 200) {
|
|
19616
20200
|
return {
|
|
19617
20201
|
name: "connected-api",
|
|
@@ -19649,7 +20233,7 @@ async function buildConnectedApiCheck(input) {
|
|
|
19649
20233
|
message: `Connected API ${baseUrl} could not verify member-token auth: ${error instanceof Error ? error.message : String(error)}`
|
|
19650
20234
|
};
|
|
19651
20235
|
}
|
|
19652
|
-
const parsedIncidentsBody = await
|
|
20236
|
+
const parsedIncidentsBody = await parseResponseBody3(incidentsResponse);
|
|
19653
20237
|
if (incidentsResponse.status !== 200) {
|
|
19654
20238
|
return {
|
|
19655
20239
|
name: "connected-api",
|
|
@@ -19732,9 +20316,9 @@ async function doctorCommand(input, dependencies = {}) {
|
|
|
19732
20316
|
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
19733
20317
|
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
19734
20318
|
const readAuthStateImpl = dependencies.readAuthState ?? readCliAuthState;
|
|
19735
|
-
const readdir = dependencies.readdir ??
|
|
19736
|
-
const readFile = dependencies.readFile ?? ((filePath) => (0,
|
|
19737
|
-
const stat = dependencies.stat ??
|
|
20319
|
+
const readdir = dependencies.readdir ?? import_promises9.readdir;
|
|
20320
|
+
const readFile = dependencies.readFile ?? ((filePath) => (0, import_promises9.readFile)(filePath, "utf8"));
|
|
20321
|
+
const stat = dependencies.stat ?? import_promises9.stat;
|
|
19738
20322
|
const rootDirectory = cwd();
|
|
19739
20323
|
const currentTime = now();
|
|
19740
20324
|
const { check: profileCheck, profile } = await loadProfile(rootDirectory, { readFile, stat });
|
|
@@ -19765,7 +20349,7 @@ async function doctorCommand(input, dependencies = {}) {
|
|
|
19765
20349
|
|
|
19766
20350
|
// src/ingest-command.ts
|
|
19767
20351
|
var import_node_crypto5 = require("node:crypto");
|
|
19768
|
-
var
|
|
20352
|
+
var import_promises11 = require("node:fs/promises");
|
|
19769
20353
|
var import_node_path12 = require("node:path");
|
|
19770
20354
|
|
|
19771
20355
|
// ../../packages/log-parser/src/project-id.ts
|
|
@@ -20085,10 +20669,11 @@ function parseLogFile(content, input) {
|
|
|
20085
20669
|
|
|
20086
20670
|
// src/process-command.ts
|
|
20087
20671
|
var import_node_crypto4 = require("node:crypto");
|
|
20088
|
-
var
|
|
20672
|
+
var import_promises10 = require("node:fs/promises");
|
|
20089
20673
|
var import_node_path11 = require("node:path");
|
|
20090
20674
|
|
|
20091
20675
|
// ../../packages/bundle-engine/src/index.ts
|
|
20676
|
+
var DYNAMIC_SEGMENT_PATTERN2 = /^(?:\d+|[0-9a-f]{8}-[0-9a-f-]{27}|[A-Za-z0-9_-]{24,})$/;
|
|
20092
20677
|
function toIsoTimestamp(value) {
|
|
20093
20678
|
return new Date(value).toISOString();
|
|
20094
20679
|
}
|
|
@@ -20162,6 +20747,41 @@ function inferSignalTypeFromSourceEventTypes(sourceEventTypes) {
|
|
|
20162
20747
|
function extractTopFrames(stack) {
|
|
20163
20748
|
return stack.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("at ")).slice(0, 3);
|
|
20164
20749
|
}
|
|
20750
|
+
function decodeRouteSegment2(segment) {
|
|
20751
|
+
try {
|
|
20752
|
+
return decodeURIComponent(segment);
|
|
20753
|
+
} catch {
|
|
20754
|
+
return segment.replace(
|
|
20755
|
+
/%([0-9A-Fa-f]{2})/g,
|
|
20756
|
+
(_match, hexByte) => String.fromCharCode(parseInt(hexByte, 16))
|
|
20757
|
+
);
|
|
20758
|
+
}
|
|
20759
|
+
}
|
|
20760
|
+
function isDynamicRouteSegment2(segment) {
|
|
20761
|
+
if (DYNAMIC_SEGMENT_PATTERN2.test(segment)) {
|
|
20762
|
+
return true;
|
|
20763
|
+
}
|
|
20764
|
+
const decodedSegment = decodeRouteSegment2(segment);
|
|
20765
|
+
if (decodedSegment.includes("/")) {
|
|
20766
|
+
return true;
|
|
20767
|
+
}
|
|
20768
|
+
if (decodedSegment !== segment && DYNAMIC_SEGMENT_PATTERN2.test(decodedSegment)) {
|
|
20769
|
+
return true;
|
|
20770
|
+
}
|
|
20771
|
+
const strippedMalformedPercent = decodedSegment.replace(/%+/g, "");
|
|
20772
|
+
return strippedMalformedPercent !== decodedSegment && DYNAMIC_SEGMENT_PATTERN2.test(strippedMalformedPercent);
|
|
20773
|
+
}
|
|
20774
|
+
function normalizeRouteTemplate(path) {
|
|
20775
|
+
if (path === null || path.length === 0) {
|
|
20776
|
+
return null;
|
|
20777
|
+
}
|
|
20778
|
+
const pathWithoutQueryOrFragment = path.split(/[?#]/, 1)[0] ?? "";
|
|
20779
|
+
if (pathWithoutQueryOrFragment.length === 0) {
|
|
20780
|
+
return "/";
|
|
20781
|
+
}
|
|
20782
|
+
const normalizedSegments = pathWithoutQueryOrFragment.split("/").filter((segment) => segment.length > 0).map((segment) => isDynamicRouteSegment2(segment) ? "{param}" : segment);
|
|
20783
|
+
return normalizedSegments.length === 0 ? "/" : `/${normalizedSegments.join("/")}`;
|
|
20784
|
+
}
|
|
20165
20785
|
function deriveFirstApplicationFrame(errorContext) {
|
|
20166
20786
|
const firstFrame = errorContext?.top_frames[0];
|
|
20167
20787
|
if (firstFrame === void 0) {
|
|
@@ -20255,13 +20875,135 @@ function buildRequestContext(envelopes) {
|
|
|
20255
20875
|
version: 1,
|
|
20256
20876
|
method: exceptionEvent.payload.request.method,
|
|
20257
20877
|
path: exceptionEvent.payload.request.path,
|
|
20258
|
-
route_template:
|
|
20878
|
+
route_template: normalizeRouteTemplate(exceptionEvent.payload.request.path),
|
|
20259
20879
|
query: exceptionEvent.payload.request.query,
|
|
20260
20880
|
headers: exceptionEvent.payload.request.headers,
|
|
20261
20881
|
body: exceptionEvent.payload.request.body ?? null,
|
|
20262
20882
|
request_id: exceptionEvent.correlation?.request_id ?? null
|
|
20263
20883
|
};
|
|
20264
20884
|
}
|
|
20885
|
+
function titleCaseWord(value) {
|
|
20886
|
+
if (value.toLowerCase() === "github") {
|
|
20887
|
+
return "GitHub";
|
|
20888
|
+
}
|
|
20889
|
+
if (value.toLowerCase() === "api") {
|
|
20890
|
+
return "API";
|
|
20891
|
+
}
|
|
20892
|
+
return `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
|
|
20893
|
+
}
|
|
20894
|
+
function formatDependencyName(name) {
|
|
20895
|
+
return name.split("_").filter((part) => part.length > 0).map(titleCaseWord).join(" ");
|
|
20896
|
+
}
|
|
20897
|
+
function inferDependencyName(text) {
|
|
20898
|
+
const match = /\b([a-z][a-z0-9]*_api)_(?:invalid_response|error|failure|failed|unavailable|timeout)\b/.exec(text);
|
|
20899
|
+
return match?.[1] ?? null;
|
|
20900
|
+
}
|
|
20901
|
+
function buildDependenciesContext(incident, errorContext, requestContext) {
|
|
20902
|
+
if (errorContext === null) {
|
|
20903
|
+
return null;
|
|
20904
|
+
}
|
|
20905
|
+
const text = `${incident.title} ${errorContext.name} ${errorContext.message}`.toLowerCase();
|
|
20906
|
+
const dependencyName = inferDependencyName(text);
|
|
20907
|
+
if (dependencyName === null) {
|
|
20908
|
+
return null;
|
|
20909
|
+
}
|
|
20910
|
+
const displayName = formatDependencyName(dependencyName);
|
|
20911
|
+
const route = requestContext?.route_template ?? requestContext?.path ?? null;
|
|
20912
|
+
const requestDescription = requestContext !== null ? `${requestContext.method} ${route ?? requestContext.path}` : "the failing request";
|
|
20913
|
+
const invalidResponse = text.includes("invalid_response");
|
|
20914
|
+
return {
|
|
20915
|
+
version: 1,
|
|
20916
|
+
items: [
|
|
20917
|
+
{
|
|
20918
|
+
name: dependencyName,
|
|
20919
|
+
status: "failed",
|
|
20920
|
+
notes: invalidResponse ? `${displayName} returned an unexpected response shape while handling ${requestDescription}.` : `${displayName} failed while handling ${requestDescription}.`
|
|
20921
|
+
}
|
|
20922
|
+
]
|
|
20923
|
+
};
|
|
20924
|
+
}
|
|
20925
|
+
function buildSummaryGuidance(input) {
|
|
20926
|
+
if (input.errorContext === null) {
|
|
20927
|
+
return {
|
|
20928
|
+
likely_cause: null,
|
|
20929
|
+
confidence: 0,
|
|
20930
|
+
recommended_action: null
|
|
20931
|
+
};
|
|
20932
|
+
}
|
|
20933
|
+
const route = input.requestContext?.route_template ?? input.requestContext?.path ?? null;
|
|
20934
|
+
const requestDescription = input.requestContext !== null ? `${input.requestContext.method} ${route ?? input.requestContext.path}` : null;
|
|
20935
|
+
const firstDependency = input.dependenciesContext?.items[0] ?? null;
|
|
20936
|
+
const dependencyDisplayName = firstDependency !== null ? formatDependencyName(firstDependency.name) : null;
|
|
20937
|
+
const firstFrame = input.firstApplicationFrame;
|
|
20938
|
+
const frameDescription = firstFrame?.file !== null && firstFrame?.file !== void 0 ? ` in ${firstFrame.file}` : "";
|
|
20939
|
+
const invalidResponse = input.errorContext.message.toLowerCase().includes("invalid_response");
|
|
20940
|
+
let likelyCause = null;
|
|
20941
|
+
let recommendedAction = null;
|
|
20942
|
+
if (firstDependency !== null && dependencyDisplayName !== null && requestDescription !== null && invalidResponse) {
|
|
20943
|
+
likelyCause = `${dependencyDisplayName} returned a response that did not match the expected schema while handling ${requestDescription}.`;
|
|
20944
|
+
recommendedAction = `Inspect the ${dependencyDisplayName} response handling${frameDescription}, including schema validation and sanitized upstream response shape.`;
|
|
20945
|
+
} else if (firstDependency !== null && dependencyDisplayName !== null && requestDescription !== null) {
|
|
20946
|
+
likelyCause = `${dependencyDisplayName} failed while handling ${requestDescription}.`;
|
|
20947
|
+
recommendedAction = `Inspect the ${dependencyDisplayName} call path${frameDescription} and compare the captured dependency notes with upstream status.`;
|
|
20948
|
+
} else if (requestDescription !== null) {
|
|
20949
|
+
likelyCause = `${input.errorContext.name} occurred while handling ${requestDescription}${frameDescription}.`;
|
|
20950
|
+
recommendedAction = `Inspect the first application frame${frameDescription} and the captured request/response context.`;
|
|
20951
|
+
} else if (firstFrame !== null) {
|
|
20952
|
+
likelyCause = `${input.errorContext.name} originated from the first captured application frame${frameDescription}.`;
|
|
20953
|
+
recommendedAction = `Inspect the first application frame${frameDescription} and surrounding error handling.`;
|
|
20954
|
+
}
|
|
20955
|
+
if (likelyCause === null || recommendedAction === null) {
|
|
20956
|
+
return {
|
|
20957
|
+
likely_cause: null,
|
|
20958
|
+
confidence: 0,
|
|
20959
|
+
recommended_action: null
|
|
20960
|
+
};
|
|
20961
|
+
}
|
|
20962
|
+
let confidence = 0.25;
|
|
20963
|
+
if (input.requestContext !== null) confidence += 0.15;
|
|
20964
|
+
if (input.responseContext !== null) confidence += 0.1;
|
|
20965
|
+
if (firstFrame !== null && firstFrame.file !== null) confidence += 0.1;
|
|
20966
|
+
if (firstDependency !== null) confidence += 0.1;
|
|
20967
|
+
if (input.errorContext.message.length > 0) confidence += 0.05;
|
|
20968
|
+
return {
|
|
20969
|
+
likely_cause: likelyCause,
|
|
20970
|
+
confidence: Math.min(0.8, Number(confidence.toFixed(2))),
|
|
20971
|
+
recommended_action: recommendedAction
|
|
20972
|
+
};
|
|
20973
|
+
}
|
|
20974
|
+
function normalizeBaseUrl4(value) {
|
|
20975
|
+
const trimmed = value?.trim();
|
|
20976
|
+
if (trimmed === void 0 || trimmed.length === 0) {
|
|
20977
|
+
return null;
|
|
20978
|
+
}
|
|
20979
|
+
return trimmed.replace(/\/+$/, "");
|
|
20980
|
+
}
|
|
20981
|
+
function buildLinks(incident, linkBaseUrls) {
|
|
20982
|
+
const apiBaseUrl = normalizeBaseUrl4(linkBaseUrls?.api);
|
|
20983
|
+
const appBaseUrl = normalizeBaseUrl4(linkBaseUrls?.app);
|
|
20984
|
+
const docsBaseUrl = normalizeBaseUrl4(linkBaseUrls?.docs);
|
|
20985
|
+
const incidentPath = `/v1/incidents/${encodeURIComponent(incident.incident_id)}`;
|
|
20986
|
+
const appIncidentPath = `/incidents/${encodeURIComponent(incident.incident_id)}`;
|
|
20987
|
+
const appProjectPath = `/projects/${encodeURIComponent(incident.project_id)}`;
|
|
20988
|
+
return {
|
|
20989
|
+
self: apiBaseUrl !== null ? `${apiBaseUrl}${incidentPath}/bundle` : null,
|
|
20990
|
+
reproduction: apiBaseUrl !== null ? `${apiBaseUrl}${incidentPath}/reproduction` : null,
|
|
20991
|
+
incident: appBaseUrl !== null ? `${appBaseUrl}${appIncidentPath}` : null,
|
|
20992
|
+
project: appBaseUrl !== null ? `${appBaseUrl}${appProjectPath}` : null,
|
|
20993
|
+
docs: docsBaseUrl !== null ? `${docsBaseUrl}/bundles` : null
|
|
20994
|
+
};
|
|
20995
|
+
}
|
|
20996
|
+
function applyBundleRedaction(candidate) {
|
|
20997
|
+
const redactionResult = redact(candidate);
|
|
20998
|
+
const fields = [...new Set(redactionResult.redacted_fields)].sort();
|
|
20999
|
+
const redactedBundle = redactionResult.redacted;
|
|
21000
|
+
redactedBundle["redaction"] = {
|
|
21001
|
+
redacted: true,
|
|
21002
|
+
fields,
|
|
21003
|
+
notes: fields.length > 0 ? "Sensitive bundle fields were redacted before storage." : null
|
|
21004
|
+
};
|
|
21005
|
+
return redactedBundle;
|
|
21006
|
+
}
|
|
20265
21007
|
function buildResponseContext(envelopes) {
|
|
20266
21008
|
const requestEvent = selectLatestEnvelopeByType(envelopes, isRequestEventEnvelope);
|
|
20267
21009
|
if (requestEvent !== null) {
|
|
@@ -20394,17 +21136,31 @@ function buildFrontendContext(envelopes) {
|
|
|
20394
21136
|
dom_context: domContext
|
|
20395
21137
|
};
|
|
20396
21138
|
}
|
|
20397
|
-
function buildDeployContext(envelopes, trigger) {
|
|
21139
|
+
function buildDeployContext(envelopes, trigger, configuredDeploy) {
|
|
20398
21140
|
const envelope = selectLatestEnvelopeByType(envelopes, isDeployMetadataEnvelope);
|
|
20399
|
-
if (envelope
|
|
21141
|
+
if (envelope !== null) {
|
|
21142
|
+
return {
|
|
21143
|
+
version: 1,
|
|
21144
|
+
commit_sha: envelope.payload.commit_sha,
|
|
21145
|
+
deploy_version: envelope.payload.version,
|
|
21146
|
+
branch: envelope.payload.branch,
|
|
21147
|
+
deployed_at: toIsoTimestamp(envelope.payload.deployed_at),
|
|
21148
|
+
regression_window: trigger === "regression_reopen"
|
|
21149
|
+
};
|
|
21150
|
+
}
|
|
21151
|
+
const commitSha = configuredDeploy?.commit_sha ?? null;
|
|
21152
|
+
const deployVersion = configuredDeploy?.deploy_version ?? null;
|
|
21153
|
+
const branch = configuredDeploy?.branch ?? null;
|
|
21154
|
+
const deployedAt = configuredDeploy?.deployed_at ?? null;
|
|
21155
|
+
if (commitSha === null && deployVersion === null && branch === null && deployedAt === null) {
|
|
20400
21156
|
return null;
|
|
20401
21157
|
}
|
|
20402
21158
|
return {
|
|
20403
21159
|
version: 1,
|
|
20404
|
-
commit_sha:
|
|
20405
|
-
deploy_version:
|
|
20406
|
-
branch
|
|
20407
|
-
deployed_at: toIsoTimestamp(
|
|
21160
|
+
commit_sha: commitSha,
|
|
21161
|
+
deploy_version: deployVersion,
|
|
21162
|
+
branch,
|
|
21163
|
+
deployed_at: deployedAt === null ? null : toIsoTimestamp(deployedAt),
|
|
20408
21164
|
regression_window: trigger === "regression_reopen"
|
|
20409
21165
|
};
|
|
20410
21166
|
}
|
|
@@ -20413,34 +21169,49 @@ function buildRuntimeContext(envelopes) {
|
|
|
20413
21169
|
if (backendException === null) {
|
|
20414
21170
|
return null;
|
|
20415
21171
|
}
|
|
21172
|
+
const runtime = backendException.payload.runtime;
|
|
20416
21173
|
return {
|
|
20417
21174
|
version: 1,
|
|
20418
21175
|
name: backendException.service.runtime ?? "unknown",
|
|
20419
|
-
runtime_version:
|
|
20420
|
-
platform: null,
|
|
20421
|
-
arch: null,
|
|
20422
|
-
pid: null,
|
|
20423
|
-
cwd: null,
|
|
20424
|
-
uptime_sec: null,
|
|
20425
|
-
hostname: null,
|
|
20426
|
-
thread_id: null,
|
|
21176
|
+
runtime_version: runtime.version,
|
|
21177
|
+
platform: runtime.platform ?? null,
|
|
21178
|
+
arch: runtime.arch ?? null,
|
|
21179
|
+
pid: runtime.pid ?? null,
|
|
21180
|
+
cwd: runtime.cwd ?? null,
|
|
21181
|
+
uptime_sec: runtime.uptime_sec ?? null,
|
|
21182
|
+
hostname: runtime.hostname ?? null,
|
|
21183
|
+
thread_id: runtime.thread_id ?? null,
|
|
20427
21184
|
framework: backendException.service.framework ?? null,
|
|
20428
|
-
framework_version: null,
|
|
20429
|
-
memory: null,
|
|
20430
|
-
framework_extras: null
|
|
21185
|
+
framework_version: runtime.framework_version ?? null,
|
|
21186
|
+
memory: runtime.memory ?? null,
|
|
21187
|
+
framework_extras: runtime.framework_extras ?? null
|
|
20431
21188
|
};
|
|
20432
21189
|
}
|
|
20433
|
-
function buildGitContext(envelopes) {
|
|
21190
|
+
function buildGitContext(envelopes, configuredDeploy) {
|
|
20434
21191
|
const deployEnvelope = selectLatestEnvelopeByType(envelopes, isDeployMetadataEnvelope);
|
|
20435
21192
|
if (deployEnvelope === null) {
|
|
20436
|
-
|
|
21193
|
+
const commit = configuredDeploy?.commit_sha ?? null;
|
|
21194
|
+
const branch = configuredDeploy?.branch ?? null;
|
|
21195
|
+
const repo = configuredDeploy?.repo ?? null;
|
|
21196
|
+
if (commit === null && branch === null && repo === null) {
|
|
21197
|
+
return null;
|
|
21198
|
+
}
|
|
21199
|
+
return {
|
|
21200
|
+
version: 1,
|
|
21201
|
+
commit,
|
|
21202
|
+
commit_short: commit === null ? null : commit.slice(0, 7),
|
|
21203
|
+
branch,
|
|
21204
|
+
repo,
|
|
21205
|
+
dirty: false,
|
|
21206
|
+
source: "env"
|
|
21207
|
+
};
|
|
20437
21208
|
}
|
|
20438
21209
|
return {
|
|
20439
21210
|
version: 1,
|
|
20440
21211
|
commit: deployEnvelope.payload.commit_sha,
|
|
20441
21212
|
commit_short: deployEnvelope.payload.commit_sha.slice(0, 7),
|
|
20442
21213
|
branch: deployEnvelope.payload.branch,
|
|
20443
|
-
repo: null,
|
|
21214
|
+
repo: configuredDeploy?.repo ?? null,
|
|
20444
21215
|
dirty: false,
|
|
20445
21216
|
source: "env"
|
|
20446
21217
|
};
|
|
@@ -20483,10 +21254,11 @@ function buildBundle(input) {
|
|
|
20483
21254
|
const responseContext = buildResponseContext(sourceEnvelopes);
|
|
20484
21255
|
const logsContext = buildLogsContext(sourceEnvelopes);
|
|
20485
21256
|
const frontendContext = buildFrontendContext(sourceEnvelopes);
|
|
20486
|
-
const deployContext = buildDeployContext(sourceEnvelopes, input.job.trigger);
|
|
21257
|
+
const deployContext = buildDeployContext(sourceEnvelopes, input.job.trigger, input.configuredDeploy);
|
|
20487
21258
|
const runtimeContext = buildRuntimeContext(sourceEnvelopes);
|
|
20488
|
-
const gitContext = buildGitContext(sourceEnvelopes);
|
|
21259
|
+
const gitContext = buildGitContext(sourceEnvelopes, input.configuredDeploy);
|
|
20489
21260
|
const deviceContext = buildDeviceContext(sourceEnvelopes);
|
|
21261
|
+
const dependenciesContext = buildDependenciesContext(input.incident, errorContext, requestContext);
|
|
20490
21262
|
const primarySignalType = primarySignalEnvelope !== null ? mapSignalType(primarySignalEnvelope.event_type) : inferSignalTypeFromSourceEventTypes(sourceEventTypes);
|
|
20491
21263
|
const primarySourceEvent = errorContext?.name ?? sourceEventTypes[0] ?? "backend_exception";
|
|
20492
21264
|
const firstSeenAt = new Date(input.incident.first_seen_at).toISOString();
|
|
@@ -20495,7 +21267,15 @@ function buildBundle(input) {
|
|
|
20495
21267
|
const serviceRuntime = input.incident.service_runtime ?? selectLatestEnvelope(sourceEnvelopes, (envelope) => envelope.event_type !== "probe_event")?.service.runtime ?? null;
|
|
20496
21268
|
const serviceFramework = input.incident.service_framework ?? selectLatestEnvelope(sourceEnvelopes, (envelope) => envelope.event_type !== "probe_event")?.service.framework ?? null;
|
|
20497
21269
|
const customerVisible = frontendContext !== null;
|
|
20498
|
-
|
|
21270
|
+
const firstApplicationFrame = deriveFirstApplicationFrame(errorContext);
|
|
21271
|
+
const summaryGuidance = buildSummaryGuidance({
|
|
21272
|
+
errorContext,
|
|
21273
|
+
requestContext,
|
|
21274
|
+
responseContext,
|
|
21275
|
+
dependenciesContext,
|
|
21276
|
+
firstApplicationFrame
|
|
21277
|
+
});
|
|
21278
|
+
const candidate = {
|
|
20499
21279
|
bundle_version: 1,
|
|
20500
21280
|
bundle_id: `bnd_${input.incident.incident_id}`,
|
|
20501
21281
|
bundle_type: "failure",
|
|
@@ -20530,13 +21310,13 @@ function buildBundle(input) {
|
|
|
20530
21310
|
summary: {
|
|
20531
21311
|
title: input.incident.title,
|
|
20532
21312
|
description: `Deterministic bundle generated from ${input.job.trigger}`,
|
|
20533
|
-
likely_cause:
|
|
20534
|
-
confidence:
|
|
20535
|
-
recommended_action:
|
|
21313
|
+
likely_cause: summaryGuidance.likely_cause,
|
|
21314
|
+
confidence: summaryGuidance.confidence,
|
|
21315
|
+
recommended_action: summaryGuidance.recommended_action,
|
|
20536
21316
|
severity: input.incident.severity,
|
|
20537
21317
|
error_type: primarySourceEvent,
|
|
20538
21318
|
error_message: errorContext?.message ?? input.incident.title,
|
|
20539
|
-
first_application_frame:
|
|
21319
|
+
first_application_frame: firstApplicationFrame,
|
|
20540
21320
|
primary_signal: primarySignalType,
|
|
20541
21321
|
signals: {
|
|
20542
21322
|
new_deploy: input.job.trigger === "deploy_metadata",
|
|
@@ -20561,7 +21341,7 @@ function buildBundle(input) {
|
|
|
20561
21341
|
deploy: deployContext,
|
|
20562
21342
|
runtime: runtimeContext,
|
|
20563
21343
|
git: gitContext,
|
|
20564
|
-
dependencies:
|
|
21344
|
+
dependencies: dependenciesContext,
|
|
20565
21345
|
probe_data: {
|
|
20566
21346
|
version: 1,
|
|
20567
21347
|
items: input.probeDataItems
|
|
@@ -20582,11 +21362,7 @@ function buildBundle(input) {
|
|
|
20582
21362
|
production_verified: false
|
|
20583
21363
|
},
|
|
20584
21364
|
links: {
|
|
20585
|
-
|
|
20586
|
-
reproduction: null,
|
|
20587
|
-
incident: null,
|
|
20588
|
-
project: null,
|
|
20589
|
-
docs: null
|
|
21365
|
+
...buildLinks(input.incident, input.linkBaseUrls)
|
|
20590
21366
|
},
|
|
20591
21367
|
redaction: {
|
|
20592
21368
|
redacted: true,
|
|
@@ -20599,7 +21375,8 @@ function buildBundle(input) {
|
|
|
20599
21375
|
generator_version: "worker-build-bundle-v2",
|
|
20600
21376
|
generation_number: input.bundleMetadata.generation_number
|
|
20601
21377
|
}
|
|
20602
|
-
}
|
|
21378
|
+
};
|
|
21379
|
+
return BundleV1Schema.parse(applyBundleRedaction(candidate));
|
|
20603
21380
|
}
|
|
20604
21381
|
|
|
20605
21382
|
// ../../packages/repro-engine/src/index.ts
|
|
@@ -20619,6 +21396,44 @@ function shellQuote(value) {
|
|
|
20619
21396
|
function sortRecordEntries(record) {
|
|
20620
21397
|
return Object.entries(record).sort(([left], [right]) => left.localeCompare(right));
|
|
20621
21398
|
}
|
|
21399
|
+
var REPLAY_HEADER_PRIORITY = [
|
|
21400
|
+
"authorization",
|
|
21401
|
+
"cookie",
|
|
21402
|
+
"accept",
|
|
21403
|
+
"content-type",
|
|
21404
|
+
"origin",
|
|
21405
|
+
"accept-language",
|
|
21406
|
+
"access-control-request-method",
|
|
21407
|
+
"access-control-request-headers",
|
|
21408
|
+
"x-request-id",
|
|
21409
|
+
"x-correlation-id",
|
|
21410
|
+
"x-debugbundle-trace-id"
|
|
21411
|
+
];
|
|
21412
|
+
var DROPPED_REPLAY_HEADERS = /* @__PURE__ */ new Set([
|
|
21413
|
+
"host",
|
|
21414
|
+
"x-forwarded-host",
|
|
21415
|
+
"x-forwarded-proto",
|
|
21416
|
+
"connection",
|
|
21417
|
+
"keep-alive",
|
|
21418
|
+
"transfer-encoding",
|
|
21419
|
+
"upgrade",
|
|
21420
|
+
"te",
|
|
21421
|
+
"trailer",
|
|
21422
|
+
"proxy-connection",
|
|
21423
|
+
"accept-encoding",
|
|
21424
|
+
"content-length",
|
|
21425
|
+
"cache-control",
|
|
21426
|
+
"pragma",
|
|
21427
|
+
"priority",
|
|
21428
|
+
"sec-ch-ua",
|
|
21429
|
+
"sec-ch-ua-mobile",
|
|
21430
|
+
"sec-ch-ua-platform",
|
|
21431
|
+
"sec-fetch-dest",
|
|
21432
|
+
"sec-fetch-mode",
|
|
21433
|
+
"sec-fetch-site",
|
|
21434
|
+
"sec-fetch-user",
|
|
21435
|
+
"user-agent"
|
|
21436
|
+
]);
|
|
20622
21437
|
function serializeScalarValue(value) {
|
|
20623
21438
|
if (typeof value === "string") {
|
|
20624
21439
|
return value;
|
|
@@ -20697,12 +21512,25 @@ function buildStructuredReplayQuery(query) {
|
|
|
20697
21512
|
return hasStructuredQueryAmbiguity(normalizedQuery) ? normalizedQuery : void 0;
|
|
20698
21513
|
}
|
|
20699
21514
|
function buildReplayHeaders(headers) {
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
|
|
21515
|
+
const entries = sortRecordEntries(headers).filter(([headerName]) => !DROPPED_REPLAY_HEADERS.has(headerName.toLowerCase())).map(([headerName, headerValue]) => [headerName, normalizeHeaderValue(headerValue)]);
|
|
21516
|
+
entries.sort(([left], [right]) => {
|
|
21517
|
+
const leftPriority = REPLAY_HEADER_PRIORITY.indexOf(left.toLowerCase());
|
|
21518
|
+
const rightPriority = REPLAY_HEADER_PRIORITY.indexOf(right.toLowerCase());
|
|
21519
|
+
if (leftPriority !== -1 || rightPriority !== -1) {
|
|
21520
|
+
if (leftPriority === -1) {
|
|
21521
|
+
return 1;
|
|
21522
|
+
}
|
|
21523
|
+
if (rightPriority === -1) {
|
|
21524
|
+
return -1;
|
|
21525
|
+
}
|
|
21526
|
+
return leftPriority - rightPriority;
|
|
21527
|
+
}
|
|
21528
|
+
return left.localeCompare(right);
|
|
21529
|
+
});
|
|
21530
|
+
return Object.fromEntries(entries);
|
|
20703
21531
|
}
|
|
20704
21532
|
function expandHeaderValues(headers) {
|
|
20705
|
-
return
|
|
21533
|
+
return Object.entries(headers).flatMap(([headerName, headerValue]) => {
|
|
20706
21534
|
if (Array.isArray(headerValue)) {
|
|
20707
21535
|
return headerValue.map((item) => [headerName, serializeScalarValue(item)]);
|
|
20708
21536
|
}
|
|
@@ -21211,11 +22039,11 @@ function serializeState(state) {
|
|
|
21211
22039
|
}
|
|
21212
22040
|
async function processCommand(input, dependencies = {}) {
|
|
21213
22041
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
21214
|
-
const mkdir = dependencies.mkdir ??
|
|
21215
|
-
const readFile = dependencies.readFile ?? ((filePath) => (0,
|
|
21216
|
-
const readdir = dependencies.readdir ??
|
|
21217
|
-
const stat = dependencies.stat ??
|
|
21218
|
-
const writeFile = dependencies.writeFile ?? ((filePath, content) => (0,
|
|
22042
|
+
const mkdir = dependencies.mkdir ?? import_promises10.mkdir;
|
|
22043
|
+
const readFile = dependencies.readFile ?? ((filePath) => (0, import_promises10.readFile)(filePath, "utf8"));
|
|
22044
|
+
const readdir = dependencies.readdir ?? import_promises10.readdir;
|
|
22045
|
+
const stat = dependencies.stat ?? import_promises10.stat;
|
|
22046
|
+
const writeFile = dependencies.writeFile ?? ((filePath, content) => (0, import_promises10.writeFile)(filePath, content, "utf8"));
|
|
21219
22047
|
const rootDirectory = cwd();
|
|
21220
22048
|
const eventsDirectoryPath = (0, import_node_path11.join)(rootDirectory, LOCAL_EVENTS_DIRECTORY_PATH2);
|
|
21221
22049
|
const statePath = (0, import_node_path11.join)(rootDirectory, LOCAL_STATE_FILE_PATH);
|
|
@@ -21495,11 +22323,11 @@ async function ingestCommand(input, dependencies = {}) {
|
|
|
21495
22323
|
};
|
|
21496
22324
|
}
|
|
21497
22325
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
21498
|
-
const mkdir = dependencies.mkdir ?? (async (path, options) => (0,
|
|
22326
|
+
const mkdir = dependencies.mkdir ?? (async (path, options) => (0, import_promises11.mkdir)(path, options));
|
|
21499
22327
|
const processLocalEvents = dependencies.processCommand ?? processCommand;
|
|
21500
|
-
const readFile = dependencies.readFile ?? (async (path) => (0,
|
|
21501
|
-
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0,
|
|
21502
|
-
const writeFile = dependencies.writeFile ?? (async (path, content) => (0,
|
|
22328
|
+
const readFile = dependencies.readFile ?? (async (path) => (0, import_promises11.readFile)(path, "utf8"));
|
|
22329
|
+
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0, import_promises11.rename)(sourcePath, destinationPath));
|
|
22330
|
+
const writeFile = dependencies.writeFile ?? (async (path, content) => (0, import_promises11.writeFile)(path, content, "utf8"));
|
|
21503
22331
|
try {
|
|
21504
22332
|
const rootDirectory = cwd();
|
|
21505
22333
|
const profile = await readProfile(rootDirectory, readFile);
|
|
@@ -21556,14 +22384,14 @@ async function ingestCommand(input, dependencies = {}) {
|
|
|
21556
22384
|
}
|
|
21557
22385
|
|
|
21558
22386
|
// src/watch-command.ts
|
|
21559
|
-
var
|
|
22387
|
+
var import_promises12 = require("node:fs/promises");
|
|
21560
22388
|
var import_node_path13 = require("node:path");
|
|
21561
|
-
function
|
|
22389
|
+
function normalizeBaseUrl5(baseUrl) {
|
|
21562
22390
|
return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
21563
22391
|
}
|
|
21564
22392
|
async function sendEventsToApi(input, dependencies) {
|
|
21565
22393
|
const fetchImpl = dependencies?.fetchImpl ?? fetch;
|
|
21566
|
-
const response = await fetchImpl(`${
|
|
22394
|
+
const response = await fetchImpl(`${normalizeBaseUrl5(input.baseUrl)}/v1/events`, {
|
|
21567
22395
|
method: "POST",
|
|
21568
22396
|
headers: {
|
|
21569
22397
|
accept: "application/json",
|
|
@@ -21600,18 +22428,18 @@ async function watchCommand(input, dependencies = {}) {
|
|
|
21600
22428
|
};
|
|
21601
22429
|
}
|
|
21602
22430
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
21603
|
-
const mkdir = dependencies.mkdir ?? (async (path, options) => (0,
|
|
22431
|
+
const mkdir = dependencies.mkdir ?? (async (path, options) => (0, import_promises12.mkdir)(path, options));
|
|
21604
22432
|
const pollIntervalMs = dependencies.pollIntervalMs ?? 1e3;
|
|
21605
22433
|
const processLocalEvents = dependencies.processCommand ?? processCommand;
|
|
21606
|
-
const readFile = dependencies.readFile ?? (async (path) => (0,
|
|
22434
|
+
const readFile = dependencies.readFile ?? (async (path) => (0, import_promises12.readFile)(path));
|
|
21607
22435
|
const readEnv = dependencies.readEnv ?? ((name) => process.env[name]);
|
|
21608
|
-
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0,
|
|
22436
|
+
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0, import_promises12.rename)(sourcePath, destinationPath));
|
|
21609
22437
|
const fetchDependencies = dependencies.fetchImpl === void 0 ? void 0 : { fetchImpl: dependencies.fetchImpl };
|
|
21610
22438
|
const sendEvents = dependencies.sendEvents ?? ((requestInput) => sendEventsToApi(requestInput, fetchDependencies));
|
|
21611
22439
|
const signal = dependencies.signal;
|
|
21612
22440
|
const sleep = dependencies.sleep ?? (async (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
21613
|
-
const stat = dependencies.stat ??
|
|
21614
|
-
const writeFile = dependencies.writeFile ?? (async (path, content) => (0,
|
|
22441
|
+
const stat = dependencies.stat ?? import_promises12.stat;
|
|
22442
|
+
const writeFile = dependencies.writeFile ?? (async (path, content) => (0, import_promises12.writeFile)(path, content, "utf8"));
|
|
21615
22443
|
try {
|
|
21616
22444
|
const rootDirectory = cwd();
|
|
21617
22445
|
const profile = await readProfile(rootDirectory, async (path) => (await readFile(path)).toString("utf8"));
|
|
@@ -21733,7 +22561,7 @@ async function watchCommand(input, dependencies = {}) {
|
|
|
21733
22561
|
}
|
|
21734
22562
|
|
|
21735
22563
|
// src/setup-command.ts
|
|
21736
|
-
var
|
|
22564
|
+
var import_promises13 = require("node:fs/promises");
|
|
21737
22565
|
var import_node_path14 = require("node:path");
|
|
21738
22566
|
var MANAGED_AGENTS_START = "<!-- debugbundle:start -->";
|
|
21739
22567
|
var MANAGED_AGENTS_END = "<!-- debugbundle:end -->";
|
|
@@ -22280,13 +23108,13 @@ async function buildProfile(rootDirectory, dependencies) {
|
|
|
22280
23108
|
async function setupCommand(input, dependencies = {}) {
|
|
22281
23109
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
22282
23110
|
const mkdir = dependencies.mkdir ?? (async (path, options) => {
|
|
22283
|
-
await (0,
|
|
23111
|
+
await (0, import_promises13.mkdir)(path, options);
|
|
22284
23112
|
});
|
|
22285
|
-
const readFile = dependencies.readFile ?? (async (path) => (0,
|
|
22286
|
-
const readdir = dependencies.readdir ?? (async (path) => (0,
|
|
22287
|
-
const remove = dependencies.remove ?? (async (path, options) => (0,
|
|
22288
|
-
const stat = dependencies.stat ?? (async (path) => (0,
|
|
22289
|
-
const writeFile = dependencies.writeFile ?? (async (path, content) => (0,
|
|
23113
|
+
const readFile = dependencies.readFile ?? (async (path) => (0, import_promises13.readFile)(path, "utf8"));
|
|
23114
|
+
const readdir = dependencies.readdir ?? (async (path) => (0, import_promises13.readdir)(path));
|
|
23115
|
+
const remove = dependencies.remove ?? (async (path, options) => (0, import_promises13.rm)(path, options));
|
|
23116
|
+
const stat = dependencies.stat ?? (async (path) => (0, import_promises13.stat)(path));
|
|
23117
|
+
const writeFile = dependencies.writeFile ?? (async (path, content) => (0, import_promises13.writeFile)(path, content, "utf8"));
|
|
22290
23118
|
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
22291
23119
|
const rootDirectory = cwd();
|
|
22292
23120
|
const packageJson = await readJsonFile2((0, import_node_path14.join)(rootDirectory, "package.json"), readFile);
|
|
@@ -22387,66 +23215,6 @@ async function setupCommand(input, dependencies = {}) {
|
|
|
22387
23215
|
}
|
|
22388
23216
|
}
|
|
22389
23217
|
|
|
22390
|
-
// src/login-command.ts
|
|
22391
|
-
var LoginCommandInputSchema = external_exports.object({
|
|
22392
|
-
bearerToken: external_exports.string().trim().min(1),
|
|
22393
|
-
baseUrl: external_exports.string().url().default("https://api.debugbundle.com")
|
|
22394
|
-
});
|
|
22395
|
-
function formatLoginOutput(authState, authFilePath) {
|
|
22396
|
-
return [
|
|
22397
|
-
"Authenticated: yes",
|
|
22398
|
-
`Base URL: ${authState.base_url}`,
|
|
22399
|
-
`Auth File: ${authFilePath}`,
|
|
22400
|
-
`Token: ${buildTokenPreview(authState.bearer_token)}`
|
|
22401
|
-
].join("\n");
|
|
22402
|
-
}
|
|
22403
|
-
function validateMemberToken(token) {
|
|
22404
|
-
return token.startsWith("dbundle_mem_");
|
|
22405
|
-
}
|
|
22406
|
-
async function loginCommand(input, dependencies) {
|
|
22407
|
-
const parsedInput = LoginCommandInputSchema.safeParse({
|
|
22408
|
-
bearerToken: input.bearerToken,
|
|
22409
|
-
baseUrl: input.baseUrl ?? "https://api.debugbundle.com"
|
|
22410
|
-
});
|
|
22411
|
-
if (!parsedInput.success || !validateMemberToken(parsedInput.data.bearerToken)) {
|
|
22412
|
-
return {
|
|
22413
|
-
exitCode: 4,
|
|
22414
|
-
output: "Invalid member token."
|
|
22415
|
-
};
|
|
22416
|
-
}
|
|
22417
|
-
const authState = {
|
|
22418
|
-
bearer_token: parsedInput.data.bearerToken,
|
|
22419
|
-
base_url: parsedInput.data.baseUrl
|
|
22420
|
-
};
|
|
22421
|
-
const writeAuthState = dependencies?.writeAuthState ?? persistCliAuthState;
|
|
22422
|
-
try {
|
|
22423
|
-
const writeInput = {
|
|
22424
|
-
authState
|
|
22425
|
-
};
|
|
22426
|
-
if (input.authFilePath !== void 0) {
|
|
22427
|
-
writeInput.authFilePath = input.authFilePath;
|
|
22428
|
-
}
|
|
22429
|
-
const persistedPath = await writeAuthState(writeInput) ?? (input.authFilePath ?? "");
|
|
22430
|
-
const payload = {
|
|
22431
|
-
authenticated: true,
|
|
22432
|
-
auth: {
|
|
22433
|
-
base_url: authState.base_url,
|
|
22434
|
-
token_preview: buildTokenPreview(authState.bearer_token)
|
|
22435
|
-
},
|
|
22436
|
-
auth_file_path: persistedPath
|
|
22437
|
-
};
|
|
22438
|
-
return {
|
|
22439
|
-
exitCode: 0,
|
|
22440
|
-
output: input.json ? JSON.stringify(payload) : formatLoginOutput(authState, payload.auth_file_path)
|
|
22441
|
-
};
|
|
22442
|
-
} catch (error) {
|
|
22443
|
-
return {
|
|
22444
|
-
exitCode: 1,
|
|
22445
|
-
output: error instanceof Error ? error.message : String(error)
|
|
22446
|
-
};
|
|
22447
|
-
}
|
|
22448
|
-
}
|
|
22449
|
-
|
|
22450
23218
|
// src/profile-command.ts
|
|
22451
23219
|
function formatProfileValidationErrors(errors) {
|
|
22452
23220
|
return [
|
|
@@ -23350,7 +24118,7 @@ async function listServicesWithAuthCommand(input, dependencies) {
|
|
|
23350
24118
|
}
|
|
23351
24119
|
|
|
23352
24120
|
// src/verify-command.ts
|
|
23353
|
-
var
|
|
24121
|
+
var import_promises14 = require("node:fs/promises");
|
|
23354
24122
|
var import_node_path15 = require("node:path");
|
|
23355
24123
|
function resolveOverallStatus2(checks) {
|
|
23356
24124
|
if (checks.some((check) => check.status === "error" || check.status === "missing")) {
|
|
@@ -23423,7 +24191,7 @@ function buildCloudSuggestedActions(status, incidentId, mode = "passive_recent_i
|
|
|
23423
24191
|
];
|
|
23424
24192
|
}
|
|
23425
24193
|
return [
|
|
23426
|
-
"Run debugbundle login to create ~/.debugbundle/auth.json before verifying cloud traffic.",
|
|
24194
|
+
"Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> to create ~/.debugbundle/auth.json before verifying cloud traffic.",
|
|
23427
24195
|
"Generate a live cloud request, then re-run debugbundle verify cloud with the correct project and service filters."
|
|
23428
24196
|
];
|
|
23429
24197
|
}
|
|
@@ -23608,14 +24376,14 @@ async function writeVerificationEventBatch(input, dependencies) {
|
|
|
23608
24376
|
async function verifyLocalCommand(input, dependencies = {}) {
|
|
23609
24377
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
23610
24378
|
const mkdir = dependencies.mkdir ?? (async (path, options) => {
|
|
23611
|
-
await (0,
|
|
24379
|
+
await (0, import_promises14.mkdir)(path, options);
|
|
23612
24380
|
});
|
|
23613
24381
|
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
23614
24382
|
const processLocal = dependencies.processCommand ?? processCommand;
|
|
23615
24383
|
const readVerifiedLocalState = dependencies.readLocalState ?? readLocalState;
|
|
23616
24384
|
const readVerifiedLocalBundle = dependencies.getLocalBundle ?? getLocalBundle;
|
|
23617
|
-
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0,
|
|
23618
|
-
const writeFile = dependencies.writeFile ?? (async (path, content) => (0,
|
|
24385
|
+
const rename = dependencies.rename ?? (async (sourcePath, destinationPath) => (0, import_promises14.rename)(sourcePath, destinationPath));
|
|
24386
|
+
const writeFile = dependencies.writeFile ?? (async (path, content) => (0, import_promises14.writeFile)(path, content, "utf8"));
|
|
23619
24387
|
const checks = [];
|
|
23620
24388
|
function finalize(exitCode, errors, incidentId) {
|
|
23621
24389
|
return formatResult(input, exitCode, checks, errors, incidentId);
|
|
@@ -23636,7 +24404,7 @@ async function verifyLocalCommand(input, dependencies = {}) {
|
|
|
23636
24404
|
});
|
|
23637
24405
|
try {
|
|
23638
24406
|
const rootDirectory = cwd();
|
|
23639
|
-
const profile = await readProfile(rootDirectory, async (path) => (0,
|
|
24407
|
+
const profile = await readProfile(rootDirectory, async (path) => (0, import_promises14.readFile)(path, "utf8"));
|
|
23640
24408
|
const projectId = buildProjectId(profile);
|
|
23641
24409
|
const verificationNow = now();
|
|
23642
24410
|
const runId = verificationNow.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
|
|
@@ -24095,7 +24863,11 @@ var CLI_USAGE_LINES = [
|
|
|
24095
24863
|
" debugbundle verify local [--json]",
|
|
24096
24864
|
" debugbundle verify cloud --project-id <id> [--trigger-5xx] [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
|
|
24097
24865
|
" debugbundle smoke --project-id <id> [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
|
|
24866
|
+
" debugbundle login [--base-url <url>] [--auth-file <path>] [--json]",
|
|
24098
24867
|
" debugbundle login <member-token> [--base-url <url>] [--auth-file <path>] [--json]",
|
|
24868
|
+
" debugbundle login --github [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
|
|
24869
|
+
" debugbundle login --github-cli [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
|
|
24870
|
+
" debugbundle login --github-device [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
|
|
24099
24871
|
" debugbundle profile validate [--json]",
|
|
24100
24872
|
" debugbundle whoami [--auth-file <path>] [--json]",
|
|
24101
24873
|
" debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <status>] [--severity <severity>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
|
|
@@ -24132,7 +24904,7 @@ var CLI_USAGE_LINES = [
|
|
|
24132
24904
|
" debugbundle token member create --label <label> [--auth-file <path>] [--json]",
|
|
24133
24905
|
" debugbundle token member revoke <token-id> [--auth-file <path>] [--json]",
|
|
24134
24906
|
" debugbundle alert list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
|
|
24135
|
-
" debugbundle alert create --project-id <id> --channel <channel> --condition <condition> [--service-id <id>] [--severity-min <level>]
|
|
24907
|
+
" 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]",
|
|
24136
24908
|
" 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]",
|
|
24137
24909
|
" debugbundle alert delete <alert-id> [--auth-file <path>] [--json]",
|
|
24138
24910
|
" debugbundle webhook list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
|
|
@@ -24163,7 +24935,7 @@ function formatUsage() {
|
|
|
24163
24935
|
}
|
|
24164
24936
|
|
|
24165
24937
|
// src/validate-command.ts
|
|
24166
|
-
var
|
|
24938
|
+
var import_promises15 = require("node:fs/promises");
|
|
24167
24939
|
var import_node_path16 = require("node:path");
|
|
24168
24940
|
var SUGGESTED_ACTIONS2 = [
|
|
24169
24941
|
"Run debugbundle setup if .debugbundle/profile.json is missing.",
|
|
@@ -24306,11 +25078,11 @@ ${managedSection}
|
|
|
24306
25078
|
async function validateCommand(input, dependencies = {}) {
|
|
24307
25079
|
const cwd = dependencies.cwd ?? (() => process.cwd());
|
|
24308
25080
|
const mkdir = dependencies.mkdir ?? (async (path, options) => {
|
|
24309
|
-
await (0,
|
|
25081
|
+
await (0, import_promises15.mkdir)(path, options);
|
|
24310
25082
|
});
|
|
24311
|
-
const readFile = dependencies.readFile ?? ((filePath) => (0,
|
|
24312
|
-
const stat = dependencies.stat ??
|
|
24313
|
-
const writeFile = dependencies.writeFile ?? (async (filePath, content) => (0,
|
|
25083
|
+
const readFile = dependencies.readFile ?? ((filePath) => (0, import_promises15.readFile)(filePath, "utf8"));
|
|
25084
|
+
const stat = dependencies.stat ?? import_promises15.stat;
|
|
25085
|
+
const writeFile = dependencies.writeFile ?? (async (filePath, content) => (0, import_promises15.writeFile)(filePath, content, "utf8"));
|
|
24314
25086
|
const rootDirectory = cwd();
|
|
24315
25087
|
const profileValidation = await validateProfile(rootDirectory, { readFile, stat });
|
|
24316
25088
|
const checks = [
|
|
@@ -24419,7 +25191,7 @@ function parseArgv(argv) {
|
|
|
24419
25191
|
positionals.push(token);
|
|
24420
25192
|
continue;
|
|
24421
25193
|
}
|
|
24422
|
-
if (token === "--fix" || token === "--json" || token === "--check-relay" || token === "--privacy" || token === "--help" || token === "--non-interactive" || token === "--local" || token === "--cloud" || token === "--events" || token === "--bundles" || token === "--all" || token === "--trigger-5xx") {
|
|
25194
|
+
if (token === "--fix" || token === "--json" || token === "--check-relay" || token === "--privacy" || token === "--help" || token === "--non-interactive" || token === "--local" || token === "--cloud" || token === "--events" || token === "--bundles" || token === "--all" || token === "--trigger-5xx" || token === "--github" || token === "--github-cli" || token === "--github-device") {
|
|
24423
25195
|
options.set(token.slice(2), true);
|
|
24424
25196
|
continue;
|
|
24425
25197
|
}
|
|
@@ -24660,7 +25432,8 @@ async function createAlertCommand(input, api) {
|
|
|
24660
25432
|
bearerToken: input.bearerToken,
|
|
24661
25433
|
projectId: input.projectId,
|
|
24662
25434
|
channel: input.channel,
|
|
24663
|
-
conditionType: input.conditionType
|
|
25435
|
+
conditionType: input.conditionType,
|
|
25436
|
+
config: input.config
|
|
24664
25437
|
};
|
|
24665
25438
|
if (input.serviceId !== void 0) {
|
|
24666
25439
|
requestInput.serviceId = input.serviceId;
|
|
@@ -24668,9 +25441,6 @@ async function createAlertCommand(input, api) {
|
|
|
24668
25441
|
if (input.severityMin !== void 0) {
|
|
24669
25442
|
requestInput.severityMin = input.severityMin;
|
|
24670
25443
|
}
|
|
24671
|
-
if (input.config !== void 0) {
|
|
24672
|
-
requestInput.config = input.config;
|
|
24673
|
-
}
|
|
24674
25444
|
if (input.isEnabled !== void 0) {
|
|
24675
25445
|
requestInput.isEnabled = input.isEnabled;
|
|
24676
25446
|
}
|
|
@@ -24692,7 +25462,8 @@ async function createAlertWithAuthCommand(input, dependencies) {
|
|
|
24692
25462
|
bearerToken: authState.bearer_token,
|
|
24693
25463
|
projectId: input.projectId,
|
|
24694
25464
|
channel: input.channel,
|
|
24695
|
-
conditionType: input.conditionType
|
|
25465
|
+
conditionType: input.conditionType,
|
|
25466
|
+
config: input.config
|
|
24696
25467
|
};
|
|
24697
25468
|
if (input.serviceId !== void 0) {
|
|
24698
25469
|
commandInput.serviceId = input.serviceId;
|
|
@@ -24700,9 +25471,6 @@ async function createAlertWithAuthCommand(input, dependencies) {
|
|
|
24700
25471
|
if (input.severityMin !== void 0) {
|
|
24701
25472
|
commandInput.severityMin = input.severityMin;
|
|
24702
25473
|
}
|
|
24703
|
-
if (input.config !== void 0) {
|
|
24704
|
-
commandInput.config = input.config;
|
|
24705
|
-
}
|
|
24706
25474
|
if (input.isEnabled !== void 0) {
|
|
24707
25475
|
commandInput.isEnabled = input.isEnabled;
|
|
24708
25476
|
}
|
|
@@ -27701,9 +28469,10 @@ async function handleAlertCommand(parsedArgv, dependencies) {
|
|
|
27701
28469
|
input.severityMin = severityMin;
|
|
27702
28470
|
}
|
|
27703
28471
|
const config = readJsonOption(parsedArgv, "config-json");
|
|
27704
|
-
if (config
|
|
27705
|
-
|
|
28472
|
+
if (config === void 0 || typeof config !== "object" || config === null) {
|
|
28473
|
+
throw new CliInputError("Missing required option --config-json.");
|
|
27706
28474
|
}
|
|
28475
|
+
input.config = config;
|
|
27707
28476
|
const isEnabled = readBooleanStringOption(parsedArgv, "is-enabled");
|
|
27708
28477
|
if (isEnabled !== void 0) {
|
|
27709
28478
|
input.isEnabled = isEnabled;
|
|
@@ -28082,15 +28851,30 @@ ${formatUsage()}`
|
|
|
28082
28851
|
return await (dependencies.smokeCommand ?? smokeCommand)(input);
|
|
28083
28852
|
}
|
|
28084
28853
|
if (command === "login") {
|
|
28085
|
-
expectNoUnknownOptions(parsedArgv, ["auth-file", "base-url", "json"]);
|
|
28854
|
+
expectNoUnknownOptions(parsedArgv, ["auth-file", "base-url", "json", "github", "github-cli", "github-device", "label"]);
|
|
28086
28855
|
ensureNoExtraPositionals(parsedArgv, 2);
|
|
28087
|
-
const
|
|
28088
|
-
|
|
28089
|
-
|
|
28856
|
+
const bearerToken = parsedArgv.positionals[1];
|
|
28857
|
+
const input = appendCommonAuthOptions(parsedArgv, {});
|
|
28858
|
+
if (bearerToken !== void 0) {
|
|
28859
|
+
input.bearerToken = bearerToken;
|
|
28860
|
+
}
|
|
28090
28861
|
const baseUrl = readStringOption(parsedArgv, "base-url");
|
|
28091
28862
|
if (baseUrl !== void 0) {
|
|
28092
28863
|
input.baseUrl = baseUrl;
|
|
28093
28864
|
}
|
|
28865
|
+
if (readBooleanOption(parsedArgv, "github") === true) {
|
|
28866
|
+
input.github = true;
|
|
28867
|
+
}
|
|
28868
|
+
if (readBooleanOption(parsedArgv, "github-cli") === true) {
|
|
28869
|
+
input.githubCli = true;
|
|
28870
|
+
}
|
|
28871
|
+
if (readBooleanOption(parsedArgv, "github-device") === true) {
|
|
28872
|
+
input.githubDevice = true;
|
|
28873
|
+
}
|
|
28874
|
+
const label = readStringOption(parsedArgv, "label");
|
|
28875
|
+
if (label !== void 0) {
|
|
28876
|
+
input.label = label;
|
|
28877
|
+
}
|
|
28094
28878
|
return await (dependencies.loginCommand ?? loginCommand)(input);
|
|
28095
28879
|
}
|
|
28096
28880
|
if (command === "whoami") {
|
|
@@ -28295,7 +29079,7 @@ ${formatUsage()}`
|
|
|
28295
29079
|
}
|
|
28296
29080
|
async function main(dependencies = {}) {
|
|
28297
29081
|
const argv = dependencies.argv ?? process.argv.slice(2);
|
|
28298
|
-
const
|
|
29082
|
+
const stdout2 = dependencies.stdout ?? ((text) => process.stdout.write(text));
|
|
28299
29083
|
const stderr = dependencies.stderr ?? ((text) => process.stderr.write(text));
|
|
28300
29084
|
const setExitCode = dependencies.setExitCode ?? ((code) => {
|
|
28301
29085
|
process.exitCode = code;
|
|
@@ -28303,7 +29087,7 @@ async function main(dependencies = {}) {
|
|
|
28303
29087
|
const result = await runCli(argv, dependencies);
|
|
28304
29088
|
if (result.output.length > 0) {
|
|
28305
29089
|
if (result.exitCode === 0) {
|
|
28306
|
-
|
|
29090
|
+
stdout2(`${result.output}
|
|
28307
29091
|
`);
|
|
28308
29092
|
} else {
|
|
28309
29093
|
stderr(`${result.output}
|