mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 11:59:00 +00:00
add docs for bun publish (#14327)
This commit is contained in:
@@ -1996,7 +1996,7 @@ pub const Example = struct {
|
||||
|
||||
var is_expected_content_type = false;
|
||||
var content_type: string = "";
|
||||
for (response.headers) |header| {
|
||||
for (response.headers.list) |header| {
|
||||
if (strings.eqlCaseInsensitiveASCII(header.name, "content-type", true)) {
|
||||
content_type = header.value;
|
||||
|
||||
|
||||
@@ -561,14 +561,7 @@ pub const PublishCommand = struct {
|
||||
const prompt_for_otp = prompt_for_otp: {
|
||||
if (res.status_code != 401) break :prompt_for_otp false;
|
||||
|
||||
if (authenticate: {
|
||||
for (res.headers) |header| {
|
||||
if (strings.eqlCaseInsensitiveASCII(header.name, "www-authenticate", true)) {
|
||||
break :authenticate header.value;
|
||||
}
|
||||
}
|
||||
break :authenticate null;
|
||||
}) |@"www-authenticate"| {
|
||||
if (res.headers.get("www-authenticate")) |@"www-authenticate"| {
|
||||
var iter = strings.split(@"www-authenticate", ",");
|
||||
while (iter.next()) |part| {
|
||||
const trimmed = strings.trim(part, &strings.whitespace_chars);
|
||||
@@ -583,7 +576,7 @@ pub const PublishCommand = struct {
|
||||
Output.errGeneric("unable to authenticate, need: {s}", .{@"www-authenticate"});
|
||||
Global.crash();
|
||||
} else if (strings.containsComptime(response_buf.list.items, "one-time pass")) {
|
||||
// missing www-authenticate header but one-time pass is still included
|
||||
// missing www-authenicate header but one-time pass is still included
|
||||
break :prompt_for_otp true;
|
||||
}
|
||||
|
||||
@@ -592,7 +585,14 @@ pub const PublishCommand = struct {
|
||||
|
||||
if (!prompt_for_otp) {
|
||||
// general error
|
||||
return handleResponseErrors(directory_publish, ctx, &req, &res, &response_buf, true);
|
||||
const otp_response = false;
|
||||
return handleResponseErrors(directory_publish, ctx, &req, &res, &response_buf, otp_response);
|
||||
}
|
||||
|
||||
if (res.headers.get("npm-notice")) |notice| {
|
||||
Output.printError("\n", .{});
|
||||
Output.note("{s}", .{notice});
|
||||
Output.flush();
|
||||
}
|
||||
|
||||
const otp = try getOTP(directory_publish, ctx, registry, &response_buf, &print_buf);
|
||||
@@ -634,9 +634,16 @@ pub const PublishCommand = struct {
|
||||
|
||||
switch (otp_res.status_code) {
|
||||
400...std.math.maxInt(@TypeOf(otp_res.status_code)) => {
|
||||
return handleResponseErrors(directory_publish, ctx, &otp_req, &otp_res, &response_buf, true);
|
||||
const otp_response = true;
|
||||
return handleResponseErrors(directory_publish, ctx, &otp_req, &otp_res, &response_buf, otp_response);
|
||||
},
|
||||
else => {
|
||||
if (otp_res.headers.get("npm-notice")) |notice| {
|
||||
Output.printError("\n", .{});
|
||||
Output.note("{s}", .{notice});
|
||||
Output.flush();
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
@@ -649,7 +656,7 @@ pub const PublishCommand = struct {
|
||||
req: *const http.AsyncHTTP,
|
||||
res: *const bun.picohttp.Response,
|
||||
response_body: *MutableString,
|
||||
comptime check_for_success: bool,
|
||||
comptime otp_response: bool,
|
||||
) OOM!void {
|
||||
const message = message: {
|
||||
const source = logger.Source.initPathString("???", response_body.list.items);
|
||||
@@ -660,29 +667,40 @@ pub const PublishCommand = struct {
|
||||
}
|
||||
};
|
||||
|
||||
if (comptime check_for_success) {
|
||||
if (json.get("success")) |success_expr| {
|
||||
if (success_expr.asBool()) |successful| {
|
||||
if (successful) {
|
||||
// possible to hit this with otp responses
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// I don't think we should make this check, I cannot find code in npm
|
||||
// that does this
|
||||
// if (comptime otp_response) {
|
||||
// if (json.get("success")) |success_expr| {
|
||||
// if (success_expr.asBool()) |successful| {
|
||||
// if (successful) {
|
||||
// // possible to hit this with otp responses
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const @"error", _ = try json.getString(ctx.allocator, "error") orelse break :message null;
|
||||
break :message @"error";
|
||||
};
|
||||
|
||||
Output.prettyErrorln("\n<red>{d}<r>{s}{s}: {s}\n{s}{s}", .{
|
||||
Output.prettyErrorln("\n<red>{d}<r>{s}{s}: {s}\n", .{
|
||||
res.status_code,
|
||||
if (res.status.len > 0) " " else "",
|
||||
res.status,
|
||||
bun.fmt.redactedNpmUrl(req.url.href),
|
||||
if (message != null) "\n - " else "",
|
||||
message orelse "",
|
||||
});
|
||||
|
||||
if (message) |msg| {
|
||||
if (comptime otp_response) {
|
||||
if (res.status_code == 401 and strings.containsComptime(msg, "You must provide a one-time pass. Upgrade your client to npm@latest in order to use 2FA.")) {
|
||||
Output.prettyErrorln("\n - Received invalid OTP", .{});
|
||||
Global.crash();
|
||||
}
|
||||
}
|
||||
Output.prettyErrorln("\n - {s}", .{msg});
|
||||
}
|
||||
|
||||
Global.crash();
|
||||
}
|
||||
|
||||
@@ -810,12 +828,10 @@ pub const PublishCommand = struct {
|
||||
202 => {
|
||||
// retry
|
||||
const nanoseconds = nanoseconds: {
|
||||
default: for (res.headers) |header| {
|
||||
if (strings.eqlCaseInsensitiveASCII(header.name, "retry-after", true)) {
|
||||
const trimmed = strings.trim(header.value, &strings.whitespace_chars);
|
||||
const seconds = bun.fmt.parseInt(u32, trimmed, 10) catch break :default;
|
||||
break :nanoseconds seconds * std.time.ns_per_s;
|
||||
}
|
||||
if (res.headers.get("retry-after")) |retry| default: {
|
||||
const trimmed = strings.trim(retry, &strings.whitespace_chars);
|
||||
const seconds = bun.fmt.parseInt(u32, trimmed, 10) catch break :default;
|
||||
break :nanoseconds seconds * std.time.ns_per_s;
|
||||
}
|
||||
|
||||
break :nanoseconds 500 * std.time.ns_per_ms;
|
||||
@@ -837,13 +853,22 @@ pub const PublishCommand = struct {
|
||||
}
|
||||
};
|
||||
|
||||
return try otp_done_json.getStringCloned(ctx.allocator, "token") orelse {
|
||||
const token = try otp_done_json.getStringCloned(ctx.allocator, "token") orelse {
|
||||
Output.err("WebLogin", "missing `token` field in reponse json", .{});
|
||||
Global.crash();
|
||||
};
|
||||
|
||||
if (res.headers.get("npm-notice")) |notice| {
|
||||
Output.printError("\n", .{});
|
||||
Output.note("{s}", .{notice});
|
||||
Output.flush();
|
||||
}
|
||||
|
||||
return token;
|
||||
},
|
||||
else => {
|
||||
try handleResponseErrors(directory_publish, ctx, &req, &res, response_buf, false);
|
||||
const otp_response = false;
|
||||
try handleResponseErrors(directory_publish, ctx, &req, &res, response_buf, otp_response);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user