aboutsummaryrefslogtreecommitdiff
path: root/src/install/npm.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/install/npm.zig')
-rw-r--r--src/install/npm.zig124
1 files changed, 106 insertions, 18 deletions
diff --git a/src/install/npm.zig b/src/install/npm.zig
index 9f3f2952c..4cf1c2b71 100644
--- a/src/install/npm.zig
+++ b/src/install/npm.zig
@@ -68,8 +68,20 @@ pub const Registry = struct {
pub fn fromAPI(name: string, registry_: Api.NpmRegistry, allocator: std.mem.Allocator, env: *DotEnv.Loader) !Scope {
var registry = registry_;
+
+ // Support $ENV_VAR for registry URLs
+ if (strings.startsWithChar(registry_.url, '$')) {
+ // If it became "$ENV_VAR/", then we need to remove the trailing slash
+ if (env.get(strings.trim(registry_.url[1..], "/"))) |replaced_url| {
+ if (replaced_url.len > 1) {
+ registry.url = replaced_url;
+ }
+ }
+ }
+
var url = URL.parse(registry.url);
var auth: string = "";
+ var needs_normalize = false;
if (registry.token.len == 0) {
outer: {
@@ -79,10 +91,12 @@ pub const Registry = struct {
url.pathname = pathname;
url.path = pathname;
}
-
+ var needs_to_check_slash = true;
while (strings.lastIndexOfChar(pathname, ':')) |colon| {
var segment = pathname[colon + 1 ..];
pathname = pathname[0..colon];
+ needs_to_check_slash = false;
+ needs_normalize = true;
if (pathname.len > 1 and pathname[pathname.len - 1] == '/') {
pathname = pathname[0 .. pathname.len - 1];
}
@@ -113,6 +127,47 @@ pub const Registry = struct {
continue;
}
}
+
+ // In this case, there is only one.
+ if (needs_to_check_slash) {
+ if (strings.lastIndexOfChar(pathname, '/')) |last_slash| {
+ var remain = pathname[last_slash + 1 ..];
+ if (strings.indexOfChar(remain, '=')) |eql_i| {
+ const segment = remain[0..eql_i];
+ var value = remain[eql_i + 1 ..];
+
+ // https://github.com/yarnpkg/yarn/blob/6db39cf0ff684ce4e7de29669046afb8103fce3d/src/registries/npm-registry.js#L364
+ // Bearer Token
+ if (strings.eqlComptime(segment, "_authToken")) {
+ registry.token = value;
+ pathname = pathname[0 .. last_slash + 1];
+ needs_normalize = true;
+ break :outer;
+ }
+
+ if (strings.eqlComptime(segment, "_auth")) {
+ auth = value;
+ pathname = pathname[0 .. last_slash + 1];
+ needs_normalize = true;
+ break :outer;
+ }
+
+ if (strings.eqlComptime(segment, "username")) {
+ registry.username = value;
+ pathname = pathname[0 .. last_slash + 1];
+ needs_normalize = true;
+ break :outer;
+ }
+
+ if (strings.eqlComptime(segment, "_password")) {
+ registry.password = value;
+ pathname = pathname[0 .. last_slash + 1];
+ needs_normalize = true;
+ break :outer;
+ }
+ }
+ }
+ }
}
registry.username = env.getAuto(registry.username);
@@ -133,6 +188,16 @@ pub const Registry = struct {
registry.token = env.getAuto(registry.token);
+ if (needs_normalize) {
+ url = URL.parse(
+ try std.fmt.allocPrint(allocator, "{s}://{}/{s}/", .{
+ url.displayProtocol(),
+ url.displayHost(),
+ strings.trim(url.pathname, "/"),
+ }),
+ );
+ }
+
return Scope{ .name = name, .url = url, .token = registry.token, .auth = auth };
}
};
@@ -262,12 +327,18 @@ pub const OperatingSystem = enum(u16) {
return (@intFromEnum(this) & linux) != 0;
} else if (comptime Environment.isMac) {
return (@intFromEnum(this) & darwin) != 0;
+ } else if (comptime Environment.isWindows) {
+ return (@intFromEnum(this) & win32) != 0;
} else {
return false;
}
}
- const NameMap = ComptimeStringMap(u16, .{
+ pub inline fn has(this: OperatingSystem, other: u16) bool {
+ return (@intFromEnum(this) & other) != 0;
+ }
+
+ pub const NameMap = ComptimeStringMap(u16, .{
.{ "aix", aix },
.{ "darwin", darwin },
.{ "freebsd", freebsd },
@@ -318,7 +389,7 @@ pub const Architecture = enum(u16) {
pub const all_value: u16 = arm | arm64 | ia32 | mips | mipsel | ppc | ppc64 | s390 | s390x | x32 | x64;
- const NameMap = ComptimeStringMap(u16, .{
+ pub const NameMap = ComptimeStringMap(u16, .{
.{ "arm", arm },
.{ "arm64", arm64 },
.{ "ia32", ia32 },
@@ -332,6 +403,10 @@ pub const Architecture = enum(u16) {
.{ "x64", x64 },
});
+ pub inline fn has(this: Architecture, other: u16) bool {
+ return (@intFromEnum(this) & other) != 0;
+ }
+
pub fn isMatch(this: Architecture) bool {
if (comptime Environment.isAarch64) {
return (@intFromEnum(this) & arm64) != 0;
@@ -733,29 +808,39 @@ pub const PackageManifest = struct {
return this.findByVersion(left.version);
}
- const releases = this.pkg.releases.keys.get(this.versions);
+ if (this.findByDistTag("latest")) |result| {
+ if (group.satisfies(result.version)) {
+ if (group.flags.isSet(Semver.Query.Group.Flags.pre)) {
+ if (left.version.order(result.version, this.string_buf, this.string_buf) == .eq) {
+ // if prerelease, use latest if semver+tag match range exactly
+ return result;
+ }
+ } else {
+ return result;
+ }
+ }
+ }
- if (group.flags.isSet(Semver.Query.Group.Flags.pre)) {
- const prereleases = this.pkg.prereleases.keys.get(this.versions);
- var i = prereleases.len;
+ {
+ const releases = this.pkg.releases.keys.get(this.versions);
+ var i = releases.len;
+ // For now, this is the dumb way
while (i > 0) : (i -= 1) {
- const version = prereleases[i - 1];
- const packages = this.pkg.prereleases.values.get(this.package_versions);
+ const version = releases[i - 1];
+ const packages = this.pkg.releases.values.get(this.package_versions);
if (group.satisfies(version)) {
return .{ .version = version, .package = &packages[i - 1] };
}
}
- } else if (this.findByDistTag("latest")) |result| {
- if (group.satisfies(result.version)) return result;
}
- {
- var i = releases.len;
- // // For now, this is the dumb way
+ if (group.flags.isSet(Semver.Query.Group.Flags.pre)) {
+ const prereleases = this.pkg.prereleases.keys.get(this.versions);
+ var i = prereleases.len;
while (i > 0) : (i -= 1) {
- const version = releases[i - 1];
- const packages = this.pkg.releases.values.get(this.package_versions);
+ const version = prereleases[i - 1];
+ const packages = this.pkg.prereleases.values.get(this.package_versions);
if (group.satisfies(version)) {
return .{ .version = version, .package = &packages[i - 1] };
@@ -796,7 +881,7 @@ pub const PackageManifest = struct {
}
}
- var result = PackageManifest{};
+ var result: PackageManifest = bun.serializable(PackageManifest{});
var string_pool = String.Builder.StringPool.init(default_allocator);
defer string_pool.deinit();
@@ -1029,6 +1114,9 @@ pub const PackageManifest = struct {
var dependency_values = version_extern_strings;
var dependency_names = all_dependency_names_and_values;
var prev_extern_bin_group = extern_strings_bin_entries;
+ const empty_version = bun.serializable(PackageVersion{
+ .bin = Bin.init(),
+ });
for (versions) |prop| {
const version_name = prop.key.?.asString(allocator) orelse continue;
@@ -1048,7 +1136,7 @@ pub const PackageManifest = struct {
}
if (!parsed_version.valid) continue;
- var package_version = PackageVersion{};
+ var package_version: PackageVersion = empty_version;
if (prop.value.?.asProperty("cpu")) |cpu| {
package_version.cpu = Architecture.all;