mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
243 lines
9.0 KiB
Zig
243 lines
9.0 KiB
Zig
const std = @import("std");
|
|
const Command = @import("../cli.zig").Command;
|
|
const bun = @import("bun");
|
|
const string = bun.string;
|
|
const Output = bun.Output;
|
|
const Global = bun.Global;
|
|
const Environment = bun.Environment;
|
|
const strings = bun.strings;
|
|
const MutableString = bun.MutableString;
|
|
const stringZ = bun.stringZ;
|
|
const default_allocator = bun.default_allocator;
|
|
const C = bun.C;
|
|
|
|
const lex = bun.js_lexer;
|
|
const logger = @import("bun").logger;
|
|
|
|
const options = @import("../options.zig");
|
|
const js_parser = bun.js_parser;
|
|
const json_parser = bun.JSON;
|
|
const js_printer = bun.js_printer;
|
|
const js_ast = bun.JSAst;
|
|
const linker = @import("../linker.zig");
|
|
|
|
const sync = @import("../sync.zig");
|
|
const Api = @import("../api/schema.zig").Api;
|
|
const resolve_path = @import("../resolver/resolve_path.zig");
|
|
const configureTransformOptionsForBun = @import("../bun.js/config.zig").configureTransformOptionsForBun;
|
|
const bundler = bun.bundler;
|
|
const NodeModuleBundle = @import("../node_module_bundle.zig").NodeModuleBundle;
|
|
const GenerateNodeModuleBundle = @import("../bundler/generate_node_modules_bundle.zig");
|
|
const DotEnv = @import("../env_loader.zig");
|
|
|
|
const fs = @import("../fs.zig");
|
|
const Router = @import("../router.zig");
|
|
|
|
var estimated_input_lines_of_code_: usize = undefined;
|
|
const ServerBundleGeneratorThread = struct {
|
|
inline fn _generate(
|
|
logs: *logger.Log,
|
|
env_loader_: *DotEnv.Loader,
|
|
allocator_: std.mem.Allocator,
|
|
ctx: Command.Context,
|
|
_filepath: [*:0]const u8,
|
|
server_conf: Api.LoadedFramework,
|
|
route_conf_: ?Api.LoadedRouteConfig,
|
|
router: ?Router,
|
|
) anyerror!void {
|
|
var server_bundler = try bundler.Bundler.init(
|
|
allocator_,
|
|
logs,
|
|
try configureTransformOptionsForBun(allocator_, ctx.args),
|
|
null,
|
|
env_loader_,
|
|
);
|
|
server_bundler.configureLinker();
|
|
server_bundler.options.jsx.supports_fast_refresh = false;
|
|
|
|
server_bundler.router = router;
|
|
server_bundler.configureDefines() catch |err| {
|
|
Output.prettyErrorln("<r><red>{s}<r> loading --define or .env values for node_modules.server.bun\n", .{@errorName(err)});
|
|
return err;
|
|
};
|
|
|
|
if (ctx.debug.macros) |macros| {
|
|
server_bundler.options.macro_remap = macros;
|
|
}
|
|
|
|
var estimated_input_lines_of_code: usize = 0;
|
|
_ = try GenerateNodeModuleBundle.generate(
|
|
&server_bundler,
|
|
allocator_,
|
|
server_conf,
|
|
route_conf_,
|
|
_filepath,
|
|
&estimated_input_lines_of_code,
|
|
ctx.debug.package_bundle_map,
|
|
);
|
|
std.mem.doNotOptimizeAway(&server_bundler);
|
|
}
|
|
pub fn generate(
|
|
logs: *logger.Log,
|
|
env_loader_: *DotEnv.Loader,
|
|
ctx: Command.Context,
|
|
_filepath: [*:0]const u8,
|
|
server_conf: Api.LoadedFramework,
|
|
route_conf_: ?Api.LoadedRouteConfig,
|
|
router: ?Router,
|
|
) void {
|
|
defer Output.flush();
|
|
|
|
_generate(logs, env_loader_, default_allocator, ctx, _filepath, server_conf, route_conf_, router) catch return;
|
|
}
|
|
};
|
|
|
|
pub const BunCommand = struct {
|
|
pub fn exec(
|
|
ctx: Command.Context,
|
|
) !void {
|
|
Global.configureAllocator(.{ .long_running = true });
|
|
var allocator = ctx.allocator;
|
|
var log = ctx.log;
|
|
estimated_input_lines_of_code_ = 0;
|
|
|
|
var this_bundler = try bundler.Bundler.init(allocator, log, ctx.args, null, null);
|
|
this_bundler.configureLinker();
|
|
var filepath: [*:0]const u8 = "node_modules.bun";
|
|
var server_bundle_filepath: [*:0]const u8 = "node_modules.server.bun";
|
|
|
|
// This step is optional
|
|
// If it fails for any reason, ignore it and continue bundling
|
|
// This is partially a workaround for the 'error.MissingRoutesDir' error
|
|
this_bundler.configureRouter(true) catch {
|
|
this_bundler.options.routes.routes_enabled = false;
|
|
this_bundler.options.framework = null;
|
|
if (this_bundler.router) |*router| {
|
|
router.config.routes_enabled = false;
|
|
router.config.single_page_app_routing = false;
|
|
router.config.static_dir_enabled = false;
|
|
this_bundler.router = null;
|
|
}
|
|
this_bundler.options.node_modules_bundle = null;
|
|
this_bundler.options.node_modules_bundle_pretty_path = "";
|
|
this_bundler.options.node_modules_bundle_url = "";
|
|
};
|
|
|
|
if (ctx.debug.macros) |macros| {
|
|
this_bundler.options.macro_remap = macros;
|
|
}
|
|
|
|
var loaded_route_config: ?Api.LoadedRouteConfig = brk: {
|
|
if (this_bundler.options.routes.routes_enabled) {
|
|
break :brk this_bundler.options.routes.toAPI();
|
|
}
|
|
break :brk null;
|
|
};
|
|
var loaded_framework: ?Api.LoadedFramework = brk: {
|
|
if (this_bundler.options.framework) |*conf| {
|
|
break :brk try conf.toAPI(allocator, this_bundler.fs.top_level_dir);
|
|
}
|
|
break :brk null;
|
|
};
|
|
var env_loader = this_bundler.env;
|
|
|
|
if (ctx.debug.dump_environment_variables) {
|
|
this_bundler.dumpEnvironmentVariables();
|
|
return;
|
|
}
|
|
|
|
if (ctx.debug.dump_limits) {
|
|
fs.FileSystem.printLimits();
|
|
Global.exit(0);
|
|
return;
|
|
}
|
|
|
|
var generated_server = false;
|
|
if (this_bundler.options.framework) |*framework| {
|
|
if (framework.toAPI(allocator, this_bundler.fs.top_level_dir) catch null) |_server_conf| {
|
|
ServerBundleGeneratorThread.generate(
|
|
log,
|
|
env_loader,
|
|
ctx,
|
|
server_bundle_filepath,
|
|
_server_conf,
|
|
loaded_route_config,
|
|
this_bundler.router,
|
|
);
|
|
generated_server = true;
|
|
|
|
if (log.msgs.items.len > 0) {
|
|
try log.printForLogLevel(Output.errorWriter());
|
|
log.* = logger.Log.init(allocator);
|
|
Output.flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
|
|
// Always generate the client-only bundle
|
|
// we can revisit this decision if people ask
|
|
var node_modules_ = try GenerateNodeModuleBundle.generate(
|
|
&this_bundler,
|
|
allocator,
|
|
loaded_framework,
|
|
loaded_route_config,
|
|
filepath,
|
|
&estimated_input_lines_of_code_,
|
|
ctx.debug.package_bundle_map,
|
|
);
|
|
|
|
const estimated_input_lines_of_code = estimated_input_lines_of_code_;
|
|
|
|
if (node_modules_) |node_modules| {
|
|
if (log.errors > 0) {
|
|
try log.printForLogLevel(Output.errorWriter());
|
|
} else {
|
|
var elapsed = @divTrunc(@truncate(i64, std.time.nanoTimestamp() - ctx.start_time), @as(i64, std.time.ns_per_ms));
|
|
const print_summary = !(ctx.args.no_summary orelse false);
|
|
if (print_summary) {
|
|
var bundle = NodeModuleBundle.init(node_modules, allocator);
|
|
bundle.printSummary();
|
|
}
|
|
const indent = comptime " ";
|
|
|
|
switch (estimated_input_lines_of_code) {
|
|
0...99999 => {
|
|
if (generated_server) {
|
|
Output.prettyln(indent ++ "<d>{d:<5} LOC parsed x2", .{estimated_input_lines_of_code});
|
|
} else {
|
|
Output.prettyln(indent ++ "<d>{d:<5} LOC parsed", .{estimated_input_lines_of_code});
|
|
}
|
|
},
|
|
else => {
|
|
const formatted_loc: f32 = @floatCast(f32, @intToFloat(f64, estimated_input_lines_of_code) / 1000);
|
|
if (generated_server) {
|
|
Output.prettyln(indent ++ "<d>{d:<5.2}k LOC parsed x2", .{formatted_loc});
|
|
} else {
|
|
Output.prettyln(indent ++ "<d>{d:<5.2}k LOC parsed", .{
|
|
formatted_loc,
|
|
});
|
|
}
|
|
},
|
|
}
|
|
|
|
Output.prettyln(indent ++ "<d>{d:6}ms elapsed", .{@intCast(u32, elapsed)});
|
|
|
|
if (generated_server) {
|
|
Output.prettyln(indent ++ "<r>Saved to ./{s}, ./{s}", .{ filepath, server_bundle_filepath });
|
|
} else {
|
|
Output.prettyln(indent ++ "<r>Saved to ./{s}", .{filepath});
|
|
}
|
|
|
|
Output.flush();
|
|
|
|
try log.printForLogLevel(Output.errorWriter());
|
|
}
|
|
} else {
|
|
try log.printForLogLevel(Output.errorWriter());
|
|
}
|
|
}
|
|
}
|
|
};
|