aws-runtime-bridge 1.9.77 → 1.9.78
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/services/cli-commands.d.ts +4 -1
- package/dist/services/cli-commands.d.ts.map +1 -1
- package/dist/services/cli-commands.js +74 -74
- package/dist/services/windows-service-manager.d.ts +28 -0
- package/dist/services/windows-service-manager.d.ts.map +1 -0
- package/dist/services/windows-service-manager.js +54 -0
- package/package.json +4 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StartupConfigWizardResult } from "./startup-config-wizard.js";
|
|
2
|
+
import { type WindowsServiceManager } from "./windows-service-manager.js";
|
|
2
3
|
export interface CliCommandResult {
|
|
3
4
|
handled: boolean;
|
|
4
5
|
exitCode: number;
|
|
@@ -19,8 +20,10 @@ export interface CliCommandOptions {
|
|
|
19
20
|
platform?: NodeJS.Platform;
|
|
20
21
|
serviceUnitPath?: string;
|
|
21
22
|
executablePath?: string;
|
|
22
|
-
/** Windows 服务日志文件路径(默认 ProgramData 下的 awsb
|
|
23
|
+
/** Windows 服务日志文件路径(默认 ProgramData 下的 awsb.out.log),供 install 重定向与 log 读取。 */
|
|
23
24
|
windowsServiceLogPath?: string;
|
|
25
|
+
/** Windows 服务管理器(基于 node-windows),用于 install 操作;测试时可注入 mock。 */
|
|
26
|
+
windowsServiceManager?: WindowsServiceManager;
|
|
24
27
|
/** 检测正在运行的 bridge 进程 PID 列表(默认按平台用 pgrep / powershell)。 */
|
|
25
28
|
findRunningBridgeProcesses?: (platform: NodeJS.Platform) => number[];
|
|
26
29
|
/** 关闭指定 PID 的进程(默认按平台用 kill -9 / taskkill)。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/services/cli-commands.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/services/cli-commands.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAK5E,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAkBtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,gBAAgB,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACrD,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gEAAgE;IAChE,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,2DAA2D;IAC3D,0BAA0B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;IACrE,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC;IACrE,oCAAoC;IACpC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD;AAYD,wBAAgB,kBAAkB,CAAC,WAAW,SAA0B,GAAG,MAAM,CAMhF;AAgCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAsBvE;AA8sBD,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CA8C3B"}
|
|
@@ -4,13 +4,15 @@ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { configureStartupConfig, printConfigExampleCommand, } from "./startup-config-wizard.js";
|
|
7
|
+
import { createWindowsServiceManager, isNodeWindowsAvailable, } from "./windows-service-manager.js";
|
|
7
8
|
const SYSTEMD_SERVICE_NAME = "awsb.service";
|
|
8
9
|
const DEFAULT_SYSTEMD_UNIT_PATH = `/etc/systemd/system/${SYSTEMD_SERVICE_NAME}`;
|
|
9
10
|
const WINDOWS_SERVICE_NAME = "awsb";
|
|
10
|
-
// Windows 服务日志:
|
|
11
|
-
//
|
|
11
|
+
// Windows 服务日志:node-windows (WinSW) 的 logpath 配置项将日志输出到此目录,
|
|
12
|
+
// 生成 awsb.out.log(stdout)和 awsb.err.log(stderr)。
|
|
13
|
+
// 路径放在 ProgramData 下,保证安装用户与服务运行账户(LocalSystem)都能访问。
|
|
12
14
|
const WINDOWS_SERVICE_LOG_DIR = path.join(process.env.ProgramData || "C:\\ProgramData", "aws-runtime-bridge", "logs");
|
|
13
|
-
const WINDOWS_SERVICE_LOG_PATH = path.join(WINDOWS_SERVICE_LOG_DIR, "awsb
|
|
15
|
+
const WINDOWS_SERVICE_LOG_PATH = path.join(WINDOWS_SERVICE_LOG_DIR, "awsb.out.log");
|
|
14
16
|
function getDefaultPackageRoot() {
|
|
15
17
|
const currentFile = fileURLToPath(import.meta.url);
|
|
16
18
|
return path.resolve(path.dirname(currentFile), "..", "..");
|
|
@@ -273,100 +275,98 @@ function stopSystemdService(options) {
|
|
|
273
275
|
options.stdout("[runtime-bridge] awsb systemd 服务已停止。");
|
|
274
276
|
return { handled: true, exitCode: 0 };
|
|
275
277
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
"
|
|
278
|
+
/**
|
|
279
|
+
* Windows 服务通过 node-windows(内置 WinSW 包装器)实现 SCM 协议适配。
|
|
280
|
+
* 用户 `npm install -g aws-runtime-bridge` 时自动获得 node-windows,无需额外安装 nssm。
|
|
281
|
+
*
|
|
282
|
+
* - install: 用 node-windows 注册服务(WinSW 包装器处理 SCM 协议);
|
|
283
|
+
* - uninstall/start/stop/restart: 用 sc.exe(Windows 原生命令)直接操作 SCM。
|
|
284
|
+
*/
|
|
285
|
+
function nodeWindowsMissingError(stderr) {
|
|
286
|
+
stderr("[runtime-bridge] 未检测到 node-windows 模块。请重新安装 aws-runtime-bridge:\n" +
|
|
287
|
+
" npm install -g aws-runtime-bridge");
|
|
286
288
|
return { handled: true, exitCode: 1 };
|
|
287
289
|
}
|
|
288
290
|
/**
|
|
289
|
-
* 用
|
|
290
|
-
* -
|
|
291
|
-
* -
|
|
292
|
-
* -
|
|
293
|
-
* 日志目录创建失败不阻断安装(nssm 启动时按需创建)。
|
|
291
|
+
* 用 node-windows 安装并启动 Windows 服务。
|
|
292
|
+
* - node-windows 在 script 所在目录下创建 daemon/ 子目录(含 WinSW 包装器和 XML 配置);
|
|
293
|
+
* - logpath 配置项将日志输出到 ProgramData 下的指定目录,供 `awsb log` 读取;
|
|
294
|
+
* - 安装后用 sc.exe start 启动服务。
|
|
294
295
|
*/
|
|
295
|
-
function installWindowsService(options) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
async function installWindowsService(options) {
|
|
297
|
+
// 测试时可注入 mock manager;生产环境用 node-windows 默认实现
|
|
298
|
+
const manager = options.windowsServiceManager;
|
|
299
|
+
if (!manager && !isNodeWindowsAvailable()) {
|
|
300
|
+
return nodeWindowsMissingError(options.stderr);
|
|
299
301
|
}
|
|
300
302
|
const logPath = options.windowsServiceLogPath || WINDOWS_SERVICE_LOG_PATH;
|
|
301
303
|
const execDir = path.dirname(options.executablePath);
|
|
302
304
|
try {
|
|
303
|
-
|
|
305
|
+
const actualManager = manager || createWindowsServiceManager();
|
|
306
|
+
await actualManager.install({
|
|
307
|
+
name: WINDOWS_SERVICE_NAME,
|
|
308
|
+
description: "awsb runtime bridge",
|
|
309
|
+
script: options.executablePath,
|
|
310
|
+
workingDirectory: execDir,
|
|
311
|
+
env: [{ name: "AWS_BRIDGE_SKIP_SETUP", value: "true" }],
|
|
312
|
+
logpath: WINDOWS_SERVICE_LOG_DIR,
|
|
313
|
+
});
|
|
304
314
|
}
|
|
305
|
-
catch {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
run(["set", WINDOWS_SERVICE_NAME, "AppStdout", logPath]);
|
|
316
|
-
run(["set", WINDOWS_SERVICE_NAME, "AppStderr", logPath]);
|
|
317
|
-
run(["set", WINDOWS_SERVICE_NAME, "AppRotateFiles", "1"]);
|
|
318
|
-
run(["set", WINDOWS_SERVICE_NAME, "AppRotateBytes", "1048576"]);
|
|
319
|
-
const startResult = run(["start", WINDOWS_SERVICE_NAME]);
|
|
315
|
+
catch (error) {
|
|
316
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
317
|
+
options.stderr(`[runtime-bridge] 安装 Windows 服务失败: ${err.message}`);
|
|
318
|
+
return { handled: true, exitCode: 1 };
|
|
319
|
+
}
|
|
320
|
+
// 安装成功后启动服务
|
|
321
|
+
const startResult = options.runCommand("sc.exe", [
|
|
322
|
+
"start",
|
|
323
|
+
WINDOWS_SERVICE_NAME,
|
|
324
|
+
]);
|
|
320
325
|
if (!commandSucceeded(startResult)) {
|
|
321
|
-
options.stderr(`[runtime-bridge]
|
|
326
|
+
options.stderr(`[runtime-bridge] 启动 Windows 服务失败: ${startResult.error?.message ?? `退出码 ${startResult.status ?? "unknown"}`}`);
|
|
322
327
|
return { handled: true, exitCode: startResult.status ?? 1 };
|
|
323
328
|
}
|
|
324
329
|
options.stdout(`[runtime-bridge] awsb Windows 服务已安装并已启动(日志: ${logPath})。`);
|
|
325
330
|
return { handled: true, exitCode: 0 };
|
|
326
331
|
}
|
|
327
332
|
/**
|
|
328
|
-
* 卸载 Windows 服务(
|
|
333
|
+
* 卸载 Windows 服务(sc.exe stop + sc.exe delete)。
|
|
329
334
|
*/
|
|
330
335
|
function uninstallWindowsService(options) {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (!commandSucceeded(removeResult)) {
|
|
339
|
-
options.stderr(`[runtime-bridge] 卸载 Windows 服务失败: ${removeResult.error?.message ?? `退出码 ${removeResult.status ?? "unknown"}`}`);
|
|
340
|
-
return { handled: true, exitCode: removeResult.status ?? 1 };
|
|
336
|
+
const run = (args) => options.runCommand("sc.exe", args);
|
|
337
|
+
// 先尝试停止(服务可能未运行,忽略失败)
|
|
338
|
+
run(["stop", WINDOWS_SERVICE_NAME]);
|
|
339
|
+
const deleteResult = run(["delete", WINDOWS_SERVICE_NAME]);
|
|
340
|
+
if (!commandSucceeded(deleteResult)) {
|
|
341
|
+
options.stderr(`[runtime-bridge] 卸载 Windows 服务失败: ${deleteResult.error?.message ?? `退出码 ${deleteResult.status ?? "unknown"}`}`);
|
|
342
|
+
return { handled: true, exitCode: deleteResult.status ?? 1 };
|
|
341
343
|
}
|
|
342
344
|
options.stdout("[runtime-bridge] awsb Windows 服务已卸载。");
|
|
343
345
|
return { handled: true, exitCode: 0 };
|
|
344
346
|
}
|
|
345
347
|
/**
|
|
346
|
-
* 重启 Windows 服务(
|
|
348
|
+
* 重启 Windows 服务(sc.exe stop + sc.exe start,未运行会被启动)。
|
|
347
349
|
*/
|
|
348
350
|
function restartWindowsService(options) {
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
return { handled: true, exitCode: result.status ?? 1 };
|
|
351
|
+
const run = (args) => options.runCommand("sc.exe", args);
|
|
352
|
+
// 先停止(可能未运行,忽略失败)
|
|
353
|
+
run(["stop", WINDOWS_SERVICE_NAME]);
|
|
354
|
+
const startResult = run(["start", WINDOWS_SERVICE_NAME]);
|
|
355
|
+
if (!commandSucceeded(startResult)) {
|
|
356
|
+
options.stderr(`[runtime-bridge] 重启 Windows 服务失败: ${startResult.error?.message ?? `退出码 ${startResult.status ?? "unknown"}`}`);
|
|
357
|
+
return { handled: true, exitCode: startResult.status ?? 1 };
|
|
357
358
|
}
|
|
358
359
|
options.stdout("[runtime-bridge] awsb Windows 服务已重启。");
|
|
359
360
|
return { handled: true, exitCode: 0 };
|
|
360
361
|
}
|
|
361
362
|
/**
|
|
362
|
-
* 启动 Windows 服务(
|
|
363
|
+
* 启动 Windows 服务(sc.exe start)。
|
|
363
364
|
*/
|
|
364
365
|
function startWindowsService(options) {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const result = options.runCommand(nssm, ["start", WINDOWS_SERVICE_NAME]);
|
|
366
|
+
const result = options.runCommand("sc.exe", [
|
|
367
|
+
"start",
|
|
368
|
+
WINDOWS_SERVICE_NAME,
|
|
369
|
+
]);
|
|
370
370
|
if (!commandSucceeded(result)) {
|
|
371
371
|
options.stderr(`[runtime-bridge] 启动 Windows 服务失败: ${result.error?.message ?? `退出码 ${result.status ?? "unknown"}`}`);
|
|
372
372
|
return { handled: true, exitCode: result.status ?? 1 };
|
|
@@ -375,14 +375,13 @@ function startWindowsService(options) {
|
|
|
375
375
|
return { handled: true, exitCode: 0 };
|
|
376
376
|
}
|
|
377
377
|
/**
|
|
378
|
-
* 停止 Windows 服务(
|
|
378
|
+
* 停止 Windows 服务(sc.exe stop)。
|
|
379
379
|
*/
|
|
380
380
|
function stopWindowsService(options) {
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const result = options.runCommand(nssm, ["stop", WINDOWS_SERVICE_NAME]);
|
|
381
|
+
const result = options.runCommand("sc.exe", [
|
|
382
|
+
"stop",
|
|
383
|
+
WINDOWS_SERVICE_NAME,
|
|
384
|
+
]);
|
|
386
385
|
if (!commandSucceeded(result)) {
|
|
387
386
|
options.stderr(`[runtime-bridge] 停止 Windows 服务失败: ${result.error?.message ?? `退出码 ${result.status ?? "unknown"}`}`);
|
|
388
387
|
return { handled: true, exitCode: result.status ?? 1 };
|
|
@@ -390,7 +389,7 @@ function stopWindowsService(options) {
|
|
|
390
389
|
options.stdout("[runtime-bridge] awsb Windows 服务已停止。");
|
|
391
390
|
return { handled: true, exitCode: 0 };
|
|
392
391
|
}
|
|
393
|
-
function handleServiceCommand(argv, options, stdout, stderr) {
|
|
392
|
+
async function handleServiceCommand(argv, options, stdout, stderr) {
|
|
394
393
|
const subcommand = argv[1];
|
|
395
394
|
if (!subcommand ||
|
|
396
395
|
subcommand === "-h" ||
|
|
@@ -406,6 +405,7 @@ function handleServiceCommand(argv, options, stdout, stderr) {
|
|
|
406
405
|
platform: options.platform || process.platform,
|
|
407
406
|
serviceUnitPath: options.serviceUnitPath || DEFAULT_SYSTEMD_UNIT_PATH,
|
|
408
407
|
executablePath: options.executablePath || getDefaultExecutablePath(),
|
|
408
|
+
windowsServiceManager: options.windowsServiceManager,
|
|
409
409
|
};
|
|
410
410
|
// 仅 Linux systemd 与 Windows 服务支持 install/uninstall/restart
|
|
411
411
|
if (serviceOptions.platform !== "linux" &&
|
|
@@ -415,7 +415,7 @@ function handleServiceCommand(argv, options, stdout, stderr) {
|
|
|
415
415
|
}
|
|
416
416
|
if (subcommand === "install") {
|
|
417
417
|
return serviceOptions.platform === "win32"
|
|
418
|
-
? installWindowsService(serviceOptions)
|
|
418
|
+
? await installWindowsService(serviceOptions)
|
|
419
419
|
: installSystemdService(serviceOptions);
|
|
420
420
|
}
|
|
421
421
|
if (subcommand === "uninstall") {
|
|
@@ -636,7 +636,7 @@ export async function handleCliCommand(options = {}) {
|
|
|
636
636
|
};
|
|
637
637
|
}
|
|
638
638
|
if (command === "service") {
|
|
639
|
-
return handleServiceCommand(argv, options, stdout, stderr);
|
|
639
|
+
return await handleServiceCommand(argv, options, stdout, stderr);
|
|
640
640
|
}
|
|
641
641
|
if (command === "log") {
|
|
642
642
|
return handleLogCommand(options, stdout, stderr);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* node-windows 封装模块。
|
|
3
|
+
*
|
|
4
|
+
* node-windows 内部使用 WinSW(.NET 服务包装器)实现 SCM 协议适配,
|
|
5
|
+
* 用户 `npm install -g aws-runtime-bridge` 时自动获得,无需额外安装 nssm。
|
|
6
|
+
*
|
|
7
|
+
* 关键行为:
|
|
8
|
+
* - install 时在 `path.dirname(script)/daemon/` 下创建 winsw.exe + XML 配置;
|
|
9
|
+
* - `logpath` 配置项控制日志输出目录(WinSW 生成 `<id>.out.log` / `<id>.err.log`);
|
|
10
|
+
* - `id` = `name.replace(/[^\w]/gi,'').toLowerCase()`,对 "awsb" → "awsb"。
|
|
11
|
+
*/
|
|
12
|
+
export interface WindowsServiceConfig {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
script: string;
|
|
16
|
+
workingDirectory?: string;
|
|
17
|
+
env?: {
|
|
18
|
+
name: string;
|
|
19
|
+
value: string;
|
|
20
|
+
}[];
|
|
21
|
+
logpath?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface WindowsServiceManager {
|
|
24
|
+
install(config: WindowsServiceConfig): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function isNodeWindowsAvailable(): boolean;
|
|
27
|
+
export declare function createWindowsServiceManager(): WindowsServiceManager;
|
|
28
|
+
//# sourceMappingURL=windows-service-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-service-manager.d.ts","sourceRoot":"","sources":["../../src/services/windows-service-manager.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAiBD,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAgB,2BAA2B,IAAI,qBAAqB,CAkCnE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
3
|
+
// node-windows 是 CommonJS 包,在 ESM 中通过 createRequire 懒加载。
|
|
4
|
+
// 非Windows 平台或包未安装时返回 null。
|
|
5
|
+
let cachedServiceCtor;
|
|
6
|
+
function getNodeWindowsServiceCtor() {
|
|
7
|
+
if (cachedServiceCtor !== undefined)
|
|
8
|
+
return cachedServiceCtor;
|
|
9
|
+
try {
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
cachedServiceCtor = require("node-windows").Service;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
cachedServiceCtor = null;
|
|
15
|
+
}
|
|
16
|
+
return cachedServiceCtor;
|
|
17
|
+
}
|
|
18
|
+
export function isNodeWindowsAvailable() {
|
|
19
|
+
return getNodeWindowsServiceCtor() !== null;
|
|
20
|
+
}
|
|
21
|
+
export function createWindowsServiceManager() {
|
|
22
|
+
return {
|
|
23
|
+
async install(config) {
|
|
24
|
+
const ServiceCtor = getNodeWindowsServiceCtor();
|
|
25
|
+
if (!ServiceCtor) {
|
|
26
|
+
throw new Error("node-windows 未安装。请重新安装 aws-runtime-bridge:npm install -g aws-runtime-bridge");
|
|
27
|
+
}
|
|
28
|
+
// 确保日志目录存在
|
|
29
|
+
if (config.logpath) {
|
|
30
|
+
try {
|
|
31
|
+
mkdirSync(config.logpath, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// 日志目录创建失败不阻断安装
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const svc = new ServiceCtor({
|
|
38
|
+
name: config.name,
|
|
39
|
+
description: config.description,
|
|
40
|
+
script: config.script,
|
|
41
|
+
workingDirectory: config.workingDirectory,
|
|
42
|
+
env: config.env,
|
|
43
|
+
logpath: config.logpath,
|
|
44
|
+
logmode: "rotate",
|
|
45
|
+
});
|
|
46
|
+
await new Promise((resolve, reject) => {
|
|
47
|
+
svc.on("install", () => resolve());
|
|
48
|
+
svc.on("alreadyinstalled", () => resolve());
|
|
49
|
+
svc.on("error", (err) => reject(err));
|
|
50
|
+
svc.install();
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aws-runtime-bridge",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.78",
|
|
4
4
|
"description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"bundleDependencies": [
|
|
26
26
|
"@cc-switch/sdk"
|
|
27
27
|
],
|
|
28
|
+
"optionalDependencies": {
|
|
29
|
+
"node-windows": "^1.0.0-beta.8"
|
|
30
|
+
},
|
|
28
31
|
"engines": {
|
|
29
32
|
"node": ">=20.0.0 <25"
|
|
30
33
|
},
|