diff options
author | 2023-08-25 21:08:41 -0700 | |
---|---|---|
committer | 2023-08-25 21:08:41 -0700 | |
commit | d98a93c3181426ea0565193303d3e63d3796231c (patch) | |
tree | 71a8d96bc4b75d902643ec877c03070cca8fcf45 /src/bun.js/api/server.zig | |
parent | f70bb2497b2406e89afec3ee8a36a3b10ef66334 (diff) | |
download | bun-d98a93c3181426ea0565193303d3e63d3796231c.tar.gz bun-d98a93c3181426ea0565193303d3e63d3796231c.tar.zst bun-d98a93c3181426ea0565193303d3e63d3796231c.zip |
Automatically hot reload Bun.serve() (#4344)
* Automatically hot reload Bun.serve()
* Update doc
* Update example
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/api/server.zig')
-rw-r--r-- | src/bun.js/api/server.zig | 108 |
1 files changed, 88 insertions, 20 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 81a50a5a7..01f06ebf2 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -158,6 +158,36 @@ pub const ServerConfig = struct { inspector: bool = false, reuse_port: bool = false, + id: []const u8 = "", + allow_hot: bool = true, + + pub fn computeID(this: *const ServerConfig, allocator: std.mem.Allocator) []const u8 { + var arraylist = std.ArrayList(u8).init(allocator); + var writer = arraylist.writer(); + + writer.writeAll("[http]-") catch {}; + switch (this.address) { + .tcp => { + if (this.address.tcp.hostname) |host| { + writer.print("tcp:{s}:{d}", .{ + bun.sliceTo(host, 0), + this.address.tcp.port, + }) catch {}; + } else { + writer.print("tcp:localhost:{d}", .{ + this.address.tcp.port, + }) catch {}; + } + }, + .unix => { + writer.print("unix:{s}", .{ + bun.sliceTo(this.address.unix, 0), + }) catch {}; + }, + } + + return arraylist.items; + } pub const SSLConfig = struct { server_name: [*c]const u8 = null, @@ -794,6 +824,23 @@ pub const ServerConfig = struct { } } + if (arg.get(global, "id")) |id| { + if (id.isUndefinedOrNull()) { + args.allow_hot = false; + } else { + const id_str = id.toSlice( + global, + bun.default_allocator, + ); + + if (id_str.len > 0) { + args.id = (id_str.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(); + } else { + args.allow_hot = false; + } + } + } + if (arg.get(global, "development")) |dev| { args.development = dev.coerce(bool, global); args.reuse_port = !args.development; @@ -4867,26 +4914,8 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return JSC.jsBoolean(true); } - pub fn onReload( - this: *ThisServer, - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { - const arguments = callframe.arguments(1).slice(); - if (arguments.len < 1) { - globalThis.throwNotEnoughArguments("reload", 1, 0); - return .zero; - } - - var args_slice = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); - defer args_slice.deinit(); - var exception_ref = [_]JSC.C.JSValueRef{null}; - var exception: JSC.C.ExceptionRef = &exception_ref; - var new_config = ServerConfig.fromJS(globalThis, &args_slice, exception); - if (exception.* != null) { - globalThis.throwValue(exception_ref[0].?.value()); - return .zero; - } + pub fn onReloadFromZig(this: *ThisServer, new_config: *ServerConfig, globalThis: *JSC.JSGlobalObject) void { + httplog("onReload", .{}); // only reload those two if (this.config.onRequest != new_config.onRequest) { @@ -4915,6 +4944,30 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this.config.websocket = ws.*; } // we don't remove it } + } + + pub fn onReload( + this: *ThisServer, + globalThis: *JSC.JSGlobalObject, + callframe: *JSC.CallFrame, + ) callconv(.C) JSC.JSValue { + const arguments = callframe.arguments(1).slice(); + if (arguments.len < 1) { + globalThis.throwNotEnoughArguments("reload", 1, 0); + return .zero; + } + + var args_slice = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); + defer args_slice.deinit(); + var exception_ref = [_]JSC.C.JSValueRef{null}; + var exception: JSC.C.ExceptionRef = &exception_ref; + var new_config = ServerConfig.fromJS(globalThis, &args_slice, exception); + if (exception.* != null) { + globalThis.throwValue(exception_ref[0].?.value()); + return .zero; + } + + this.onReloadFromZig(&new_config, globalThis); return this.thisObject; } @@ -5066,6 +5119,15 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return JSC.JSValue.jsNumber(listener.getLocalPort()); } + pub fn getId( + this: *ThisServer, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSC.JSValue { + var str = bun.String.create(this.config.id); + defer str.deref(); + return str.toJS(globalThis); + } + pub fn getPendingRequests( this: *ThisServer, _: *JSC.JSGlobalObject, @@ -5170,6 +5232,12 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp } pub fn stop(this: *ThisServer, abrupt: bool) void { + if (this.config.allow_hot and this.config.id.len > 0) { + if (this.globalThis.bunVM().hotMap()) |hot| { + hot.remove(this.config.id); + } + } + this.stopListening(abrupt); this.deinitIfWeCan(); } |