nanoshell 1.2.3 → 1.3.5
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/cli/dev_server.zig +176 -5
- package/package.json +1 -1
- package/zig-out/bin/example_app.exe +0 -0
- package/zig-out/bin/nanoshell.exe +0 -0
package/cli/dev_server.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const installer = @import("installer.zig");
|
|
2
3
|
|
|
3
4
|
pub const DevServer = struct {
|
|
4
5
|
allocator: std.mem.Allocator,
|
|
@@ -8,14 +9,184 @@ pub const DevServer = struct {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
pub fn runDevMode(self: *DevServer, app_dir_name: []const u8) !void {
|
|
12
|
+
_ = app_dir_name;
|
|
11
13
|
std.log.info("=================================================================", .{});
|
|
12
|
-
std.log.info(" ⚡ NanoShell
|
|
13
|
-
std.log.info(" Watching app/ directory for
|
|
14
|
+
std.log.info(" ⚡ NanoShell Dev Server Started", .{});
|
|
15
|
+
std.log.info(" Watching app/ directory & nanoshell.json for live changes...", .{});
|
|
14
16
|
std.log.info("=================================================================", .{});
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
defer self.allocator
|
|
18
|
+
var config = installer.loadConfig(self.allocator) catch installer.AppConfig{};
|
|
19
|
+
defer config.deinit(self.allocator);
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
// Find executable inside bin/ or zig-out/bin/
|
|
22
|
+
const io = std.Io.Threaded.global_single_threaded.io();
|
|
23
|
+
const cwd = std.Io.Dir.cwd();
|
|
24
|
+
|
|
25
|
+
var found_exe: ?[]const u8 = null;
|
|
26
|
+
|
|
27
|
+
const candidate_paths = [_][]const u8{
|
|
28
|
+
"zig-out/bin/example_app.exe",
|
|
29
|
+
"bin/example_app.exe",
|
|
30
|
+
"zig-out/bin/nanoshell.exe",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
for (candidate_paths) |p| {
|
|
34
|
+
if (cwd.openFile(io, p, .{})) |f| {
|
|
35
|
+
f.close(io);
|
|
36
|
+
found_exe = p;
|
|
37
|
+
break;
|
|
38
|
+
} else |_| {}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (found_exe == null) {
|
|
42
|
+
// Search bin/ for any .exe
|
|
43
|
+
var bin_dir = cwd.openDir(io, "bin", .{ .iterate = true }) catch null;
|
|
44
|
+
if (bin_dir) |*d| {
|
|
45
|
+
defer d.close(io);
|
|
46
|
+
var iter = d.iterate();
|
|
47
|
+
while (iter.next(io) catch null) |entry| {
|
|
48
|
+
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".exe")) {
|
|
49
|
+
found_exe = try std.fmt.allocPrint(self.allocator, "bin/{s}", .{entry.name});
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var win_exe_buf: [256]u8 = undefined;
|
|
57
|
+
const exe_to_run = found_exe orelse "bin\\app.exe";
|
|
58
|
+
var pos: usize = 0;
|
|
59
|
+
for (exe_to_run) |ch| {
|
|
60
|
+
if (ch == '/') {
|
|
61
|
+
win_exe_buf[pos] = '\\';
|
|
62
|
+
} else {
|
|
63
|
+
win_exe_buf[pos] = ch;
|
|
64
|
+
}
|
|
65
|
+
pos += 1;
|
|
66
|
+
}
|
|
67
|
+
win_exe_buf[pos] = 0;
|
|
68
|
+
const win_path = win_exe_buf[0..pos];
|
|
69
|
+
|
|
70
|
+
var dev_cmd_buf: [300]u8 = undefined;
|
|
71
|
+
const dev_cmd = std.fmt.bufPrintZ(&dev_cmd_buf, "{s} --dev", .{win_path}) catch win_path;
|
|
72
|
+
|
|
73
|
+
std.log.info("Launching NanoShell runtime in DEV mode: {s}", .{dev_cmd});
|
|
74
|
+
|
|
75
|
+
// Launch app process once - native engine handles smooth in-window hot reload in dev mode
|
|
76
|
+
var child = try self.spawnChildProcess(dev_cmd);
|
|
77
|
+
defer _ = child.kill();
|
|
78
|
+
|
|
79
|
+
std.log.info("App running! In-window hot reload active for app/index.html, styles.css, app.js.", .{});
|
|
80
|
+
|
|
81
|
+
const WinApi = struct {
|
|
82
|
+
pub extern "kernel32" fn Sleep(dwMilliseconds: u32) callconv(.winapi) void;
|
|
83
|
+
pub extern "kernel32" fn GetExitCodeProcess(hProcess: std.os.windows.HANDLE, lpExitCode: *u32) callconv(.winapi) i32;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
var exit_code: u32 = 259; // STILL_ACTIVE
|
|
87
|
+
while (exit_code == 259) {
|
|
88
|
+
WinApi.Sleep(500);
|
|
89
|
+
_ = WinApi.GetExitCodeProcess(child.hProcess, &exit_code);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fn spawnChildProcess(self: *DevServer, exe_path: []const u8) !ChildProcess {
|
|
94
|
+
_ = self;
|
|
95
|
+
var cmd_utf16: [1024]u16 = undefined;
|
|
96
|
+
const len = try std.unicode.utf8ToUtf16Le(&cmd_utf16, exe_path);
|
|
97
|
+
cmd_utf16[len] = 0;
|
|
98
|
+
|
|
99
|
+
const STARTUPINFOW = extern struct {
|
|
100
|
+
cb: u32 = 104,
|
|
101
|
+
lpReserved: ?[*:0]u16 = null,
|
|
102
|
+
lpDesktop: ?[*:0]u16 = null,
|
|
103
|
+
lpTitle: ?[*:0]u16 = null,
|
|
104
|
+
dwX: u32 = 0,
|
|
105
|
+
dwY: u32 = 0,
|
|
106
|
+
dwXSize: u32 = 0,
|
|
107
|
+
dwYSize: u32 = 0,
|
|
108
|
+
dwXCountChars: u32 = 0,
|
|
109
|
+
dwYCountChars: u32 = 0,
|
|
110
|
+
dwFillAttribute: u32 = 0,
|
|
111
|
+
dwFlags: u32 = 0,
|
|
112
|
+
wShowWindow: u16 = 0,
|
|
113
|
+
cbReserved2: u16 = 0,
|
|
114
|
+
lpReserved2: ?*u8 = null,
|
|
115
|
+
hStdInput: ?std.os.windows.HANDLE = null,
|
|
116
|
+
hStdOutput: ?std.os.windows.HANDLE = null,
|
|
117
|
+
hStdError: ?std.os.windows.HANDLE = null,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const PROCESS_INFORMATION = extern struct {
|
|
121
|
+
hProcess: std.os.windows.HANDLE,
|
|
122
|
+
hThread: std.os.windows.HANDLE,
|
|
123
|
+
dwProcessId: u32,
|
|
124
|
+
dwThreadId: u32,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const WinApi = struct {
|
|
128
|
+
pub extern "kernel32" fn CreateProcessW(
|
|
129
|
+
lpApplicationName: ?[*:0]const u16,
|
|
130
|
+
lpCommandLine: ?[*:0]u16,
|
|
131
|
+
lpProcessAttributes: ?*anyopaque,
|
|
132
|
+
lpThreadAttributes: ?*anyopaque,
|
|
133
|
+
bInheritHandles: i32,
|
|
134
|
+
dwCreationFlags: u32,
|
|
135
|
+
lpEnvironment: ?*anyopaque,
|
|
136
|
+
lpCurrentDirectory: ?[*:0]const u16,
|
|
137
|
+
lpStartupInfo: *const STARTUPINFOW,
|
|
138
|
+
lpProcessInformation: *PROCESS_INFORMATION,
|
|
139
|
+
) callconv(.winapi) i32;
|
|
140
|
+
|
|
141
|
+
pub extern "kernel32" fn TerminateProcess(hProcess: std.os.windows.HANDLE, uExitCode: u32) callconv(.winapi) i32;
|
|
142
|
+
pub extern "kernel32" fn CloseHandle(hObject: std.os.windows.HANDLE) callconv(.winapi) i32;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
var si = STARTUPINFOW{};
|
|
146
|
+
var pi: PROCESS_INFORMATION = undefined;
|
|
147
|
+
|
|
148
|
+
const res = WinApi.CreateProcessW(null, @ptrCast(&cmd_utf16), null, null, 0, 0, null, null, &si, &pi);
|
|
149
|
+
if (res == 0) return error.ProcessCreationFailed;
|
|
150
|
+
|
|
151
|
+
return ChildProcess{
|
|
152
|
+
.hProcess = pi.hProcess,
|
|
153
|
+
.hThread = pi.hThread,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
fn getAppModTime(self: *DevServer) i128 {
|
|
158
|
+
_ = self;
|
|
159
|
+
const io = std.Io.Threaded.global_single_threaded.io();
|
|
160
|
+
const cwd = std.Io.Dir.cwd();
|
|
161
|
+
var max_mtime: i128 = 0;
|
|
162
|
+
|
|
163
|
+
var app_dir = cwd.openDir(io, "app", .{ .iterate = true }) catch return 0;
|
|
164
|
+
defer app_dir.close(io);
|
|
165
|
+
|
|
166
|
+
var iter = app_dir.iterate();
|
|
167
|
+
while (iter.next(io) catch null) |entry| {
|
|
168
|
+
if (entry.kind == .file) {
|
|
169
|
+
if (app_dir.statFile(io, entry.name, .{})) |st| {
|
|
170
|
+
const ns = st.mtime.toNanoseconds();
|
|
171
|
+
if (ns > max_mtime) max_mtime = ns;
|
|
172
|
+
} else |_| {}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return max_mtime;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
pub const ChildProcess = struct {
|
|
180
|
+
hProcess: std.os.windows.HANDLE,
|
|
181
|
+
hThread: std.os.windows.HANDLE,
|
|
182
|
+
|
|
183
|
+
pub fn kill(self: *ChildProcess) void {
|
|
184
|
+
const WinApi = struct {
|
|
185
|
+
pub extern "kernel32" fn TerminateProcess(hProcess: std.os.windows.HANDLE, uExitCode: u32) callconv(.winapi) i32;
|
|
186
|
+
pub extern "kernel32" fn CloseHandle(hObject: std.os.windows.HANDLE) callconv(.winapi) i32;
|
|
187
|
+
};
|
|
188
|
+
_ = WinApi.TerminateProcess(self.hProcess, 1);
|
|
189
|
+
_ = WinApi.CloseHandle(self.hProcess);
|
|
190
|
+
_ = WinApi.CloseHandle(self.hThread);
|
|
20
191
|
}
|
|
21
192
|
};
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|