@electron-memory/monitor 0.2.0 → 0.2.2

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/dist/index.d.mts CHANGED
@@ -206,6 +206,8 @@ interface MonitorConfig {
206
206
  height: number;
207
207
  /** 是否置顶,默认 false */
208
208
  alwaysOnTop: boolean;
209
+ /** 打开看板时是否自动打开 DevTools,默认 false;为 true 或环境变量 LAUNCHER_MEMORY_MONITOR_DEVTOOLS=1 时开启 */
210
+ openDevToolsOnStart: boolean;
209
211
  };
210
212
  /** 给窗口进程打标签,方便识别 */
211
213
  processLabels: Record<string, string>;
package/dist/index.d.ts CHANGED
@@ -206,6 +206,8 @@ interface MonitorConfig {
206
206
  height: number;
207
207
  /** 是否置顶,默认 false */
208
208
  alwaysOnTop: boolean;
209
+ /** 打开看板时是否自动打开 DevTools,默认 false;为 true 或环境变量 LAUNCHER_MEMORY_MONITOR_DEVTOOLS=1 时开启 */
210
+ openDevToolsOnStart: boolean;
209
211
  };
210
212
  /** 给窗口进程打标签,方便识别 */
211
213
  processLabels: Record<string, string>;
package/dist/index.js CHANGED
@@ -1112,19 +1112,48 @@ var path3 = __toESM(require("path"));
1112
1112
 
1113
1113
  // src/core/dashboard-protocol.ts
1114
1114
  var import_electron2 = require("electron");
1115
+ var import_promises = require("fs/promises");
1115
1116
  var path2 = __toESM(require("path"));
1116
- var import_node_url = require("url");
1117
1117
  var SCHEME = "emm-dashboard";
1118
1118
  var privilegedRegistered = false;
1119
1119
  var handlerRegistered = false;
1120
+ var MIME_BY_EXT = {
1121
+ ".html": "text/html; charset=utf-8",
1122
+ ".js": "text/javascript; charset=utf-8",
1123
+ ".mjs": "text/javascript; charset=utf-8",
1124
+ ".css": "text/css; charset=utf-8",
1125
+ ".json": "application/json",
1126
+ ".map": "application/json",
1127
+ ".svg": "image/svg+xml",
1128
+ ".png": "image/png",
1129
+ ".jpg": "image/jpeg",
1130
+ ".jpeg": "image/jpeg",
1131
+ ".gif": "image/gif",
1132
+ ".webp": "image/webp",
1133
+ ".ico": "image/x-icon",
1134
+ ".woff": "font/woff",
1135
+ ".woff2": "font/woff2",
1136
+ ".ttf": "font/ttf",
1137
+ ".txt": "text/plain; charset=utf-8"
1138
+ };
1120
1139
  function isPathInsideRoot(filePath, root) {
1121
1140
  const f = path2.resolve(filePath);
1122
1141
  const r = path2.resolve(root);
1123
1142
  if (f === r) {
1124
1143
  return true;
1125
1144
  }
1126
- const sep2 = r.endsWith(path2.sep) ? r : `${r}${path2.sep}`;
1127
- return f.startsWith(sep2);
1145
+ const rel = path2.relative(r, f);
1146
+ if (!rel || rel.startsWith("..") || path2.isAbsolute(rel)) {
1147
+ return false;
1148
+ }
1149
+ return true;
1150
+ }
1151
+ function corsHeaders() {
1152
+ return {
1153
+ "Access-Control-Allow-Origin": "*",
1154
+ "Access-Control-Allow-Methods": "GET, OPTIONS",
1155
+ "Access-Control-Allow-Headers": "*"
1156
+ };
1128
1157
  }
1129
1158
  function registerDashboardSchemePrivileged() {
1130
1159
  if (privilegedRegistered) {
@@ -1155,20 +1184,39 @@ function ensureDashboardProtocolHandler(uiRoot) {
1155
1184
  }
1156
1185
  handlerRegistered = true;
1157
1186
  const base = path2.resolve(uiRoot);
1158
- import_electron2.protocol.handle(SCHEME, (request) => {
1187
+ import_electron2.protocol.handle(SCHEME, async (request) => {
1188
+ if (request.method === "OPTIONS") {
1189
+ return new Response(null, { status: 204, headers: corsHeaders() });
1190
+ }
1159
1191
  try {
1160
- const { pathname } = new URL(request.url);
1161
- let rel = pathname.startsWith("/") ? pathname.slice(1) : pathname;
1192
+ let pathname;
1193
+ try {
1194
+ pathname = decodeURIComponent(new URL(request.url).pathname);
1195
+ } catch {
1196
+ return new Response("Bad URL", { status: 400, headers: corsHeaders() });
1197
+ }
1198
+ let rel = pathname.replace(/^\/+/, "");
1162
1199
  if (!rel) {
1163
1200
  rel = "index.html";
1164
1201
  }
1165
1202
  const filePath = path2.resolve(path2.join(base, rel));
1166
1203
  if (!isPathInsideRoot(filePath, base)) {
1167
- return new Response("Forbidden", { status: 403 });
1204
+ return new Response("Forbidden", { status: 403, headers: corsHeaders() });
1168
1205
  }
1169
- return import_electron2.net.fetch((0, import_node_url.pathToFileURL)(filePath).href);
1170
- } catch {
1171
- return new Response("Bad Request", { status: 400 });
1206
+ const body = await (0, import_promises.readFile)(filePath);
1207
+ const ext = path2.extname(filePath).toLowerCase();
1208
+ const mime = MIME_BY_EXT[ext] || "application/octet-stream";
1209
+ return new Response(body, {
1210
+ status: 200,
1211
+ headers: {
1212
+ "Content-Type": mime,
1213
+ "Cache-Control": "no-store",
1214
+ ...corsHeaders()
1215
+ }
1216
+ });
1217
+ } catch (err) {
1218
+ const msg = err instanceof Error ? err.message : String(err);
1219
+ return new Response(msg, { status: 404, headers: corsHeaders() });
1172
1220
  }
1173
1221
  });
1174
1222
  }
@@ -1176,6 +1224,51 @@ function getDashboardPageURL() {
1176
1224
  return `${SCHEME}://electron/index.html`;
1177
1225
  }
1178
1226
 
1227
+ // src/core/dashboard-window-hooks.ts
1228
+ function shouldOpenDevToolsShortcut(input) {
1229
+ if (input.type !== "keyDown") {
1230
+ return false;
1231
+ }
1232
+ if (input.key === "F12") {
1233
+ return true;
1234
+ }
1235
+ const k = input.key.toLowerCase();
1236
+ if (k !== "i") {
1237
+ return false;
1238
+ }
1239
+ if (input.control && input.shift) {
1240
+ return true;
1241
+ }
1242
+ if (process.platform === "darwin" && input.meta && input.alt) {
1243
+ return true;
1244
+ }
1245
+ return false;
1246
+ }
1247
+ function attachDashboardWindowHooks(win, options) {
1248
+ const wc = win.webContents;
1249
+ wc.on("before-input-event", (event, input) => {
1250
+ if (!shouldOpenDevToolsShortcut(input)) {
1251
+ return;
1252
+ }
1253
+ event.preventDefault();
1254
+ if (wc.isDevToolsOpened()) {
1255
+ wc.closeDevTools();
1256
+ } else {
1257
+ wc.openDevTools({ mode: "detach" });
1258
+ }
1259
+ });
1260
+ wc.on("did-fail-load", (_e, code, desc, url) => {
1261
+ console.error("[@electron-memory/monitor] dashboard did-fail-load", code, desc, url);
1262
+ });
1263
+ let autoOpened = false;
1264
+ wc.on("did-finish-load", () => {
1265
+ if (options.openDevToolsOnStart && !autoOpened) {
1266
+ autoOpened = true;
1267
+ wc.openDevTools({ mode: "detach" });
1268
+ }
1269
+ });
1270
+ }
1271
+
1179
1272
  // src/core/dashboard.ts
1180
1273
  var DashboardManager = class {
1181
1274
  constructor(config) {
@@ -1208,9 +1301,13 @@ var DashboardManager = class {
1208
1301
  webPreferences: {
1209
1302
  preload: preloadPath,
1210
1303
  contextIsolation: true,
1211
- nodeIntegration: false
1304
+ nodeIntegration: false,
1305
+ devTools: true
1212
1306
  }
1213
1307
  });
1308
+ attachDashboardWindowHooks(this.window, {
1309
+ openDevToolsOnStart: this.config.dashboard.openDevToolsOnStart
1310
+ });
1214
1311
  const uiRoot = path3.join(__dirname, "ui");
1215
1312
  ensureDashboardProtocolHandler(uiRoot);
1216
1313
  this.window.loadURL(getDashboardPageURL());
@@ -1364,7 +1461,8 @@ var DEFAULT_CONFIG = {
1364
1461
  dashboard: {
1365
1462
  width: 1400,
1366
1463
  height: 900,
1367
- alwaysOnTop: false
1464
+ alwaysOnTop: false,
1465
+ openDevToolsOnStart: false
1368
1466
  },
1369
1467
  processLabels: {}
1370
1468
  };
@@ -1680,7 +1778,15 @@ var ElectronMemoryMonitor = class extends import_events3.EventEmitter {
1680
1778
  this.emit("snapshot", snapshot);
1681
1779
  }
1682
1780
  mergeConfig(userConfig) {
1683
- if (!userConfig) return { ...DEFAULT_CONFIG };
1781
+ if (!userConfig) {
1782
+ return {
1783
+ ...DEFAULT_CONFIG,
1784
+ dashboard: {
1785
+ ...DEFAULT_CONFIG.dashboard,
1786
+ openDevToolsOnStart: process.env.LAUNCHER_MEMORY_MONITOR_DEVTOOLS === "1"
1787
+ }
1788
+ };
1789
+ }
1684
1790
  return {
1685
1791
  ...DEFAULT_CONFIG,
1686
1792
  ...userConfig,
@@ -1694,7 +1800,8 @@ var ElectronMemoryMonitor = class extends import_events3.EventEmitter {
1694
1800
  },
1695
1801
  dashboard: {
1696
1802
  ...DEFAULT_CONFIG.dashboard,
1697
- ...userConfig.dashboard || {}
1803
+ ...userConfig.dashboard || {},
1804
+ openDevToolsOnStart: userConfig.dashboard?.openDevToolsOnStart !== void 0 ? userConfig.dashboard.openDevToolsOnStart : process.env.LAUNCHER_MEMORY_MONITOR_DEVTOOLS === "1"
1698
1805
  },
1699
1806
  processLabels: {
1700
1807
  ...DEFAULT_CONFIG.processLabels,