feat: Windows 便携安装包构建(免装 Node.js)
新增 pnpm pack:win(scripts/pack.mjs),一键产出 nodeagent-win-x64.zip: - esbuild 打包被控端为单文件 bundle(含全部依赖,约 800KB) - 自动下载 Node.js Windows x64 运行时(npmmirror,node.exe) - 组装便携包并打 zip(node.exe + agent.mjs + install.ps1 + uninstall.ps1) 改造 install.ps1: - 优先使用包内 node.exe + agent.mjs(便携包模式) - 否则回退系统 Node.js + 仓库构建产物(开发模式) - 无 Node.js 的 Windows 机器也能一键安装 配套: - .gitignore 忽略 release/(产物体积大,不入库) - README 安装说明改为「安装包(推荐)/ 开发模式」两方式 验证:打包产物 32MB;解压后 agent.mjs 可独立运行(19 项能力、wss 监听); esbuild bundle 通过 banner 提供 createRequire 兼容 CJS 依赖(node-forge)
This commit is contained in:
1 parent
f4c605cc6d
commit
192e08b171
7 files changed
+436
-21
No files matched your search
@@ -29,3 +29,6 @@ Thumbs.db
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# 安装包构建产物(体积大,不入库)
|
||||
release/
|
||||
@@ -39,14 +39,20 @@ pnpm build
|
||||
|
||||
### 1. Windows 侧(被控端)
|
||||
|
||||
在 Windows 上以**管理员权限**运行:
|
||||
**方式 A:安装包(推荐,免装 Node.js)**
|
||||
|
||||
1. 在控制端构建安装包:`pnpm pack:win`(产物:`release/nodeagent-win-x64.zip`)
|
||||
2. 把 zip 拷到 Windows 并解压
|
||||
3. 右键以**管理员**运行其中的 `install.ps1`
|
||||
|
||||
安装脚本会使用**包内自带的 Node.js 运行时**,自动:生成预共享密钥 → 写配置 → 放行防火墙 → 注册开机自启 → 启动 Agent,并打印**密钥**与**连接命令**。
|
||||
|
||||
**方式 B:开发模式(本仓库)**
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\install.ps1
|
||||
```
|
||||
|
||||
脚本会:生成预共享密钥 → 写配置 → 放行防火墙 → 注册开机自启 → 启动 Agent,并打印**密钥**与**连接命令**。
|
||||
|
||||
### 2. Mac 侧(控制端)
|
||||
|
||||
```bash
|
||||
|
||||
+8
-1
@@ -17,10 +17,17 @@
|
||||
"test:unit": "node --test \"tests/unit/**/*.test.mjs\"",
|
||||
"test:e2e": "node tests/e2e/run.mjs",
|
||||
"test:windows": "node tests/e2e/windows.mjs",
|
||||
"verify": "node scripts/verify.mjs"
|
||||
"verify": "node scripts/verify.mjs",
|
||||
"pack:win": "node scripts/pack.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.2",
|
||||
"esbuild": "^0.28.2",
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
}
|
||||
Generated
+271
@@ -11,6 +11,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^22.10.2
|
||||
version: 22.20.4
|
||||
esbuild:
|
||||
specifier: ^0.28.2
|
||||
version: 0.28.2
|
||||
typescript:
|
||||
specifier: ^5.7.2
|
||||
version: 5.9.3
|
||||
@@ -82,6 +85,162 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.2':
|
||||
resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.28.2':
|
||||
resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.28.2':
|
||||
resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.28.2':
|
||||
resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.28.2':
|
||||
resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.28.2':
|
||||
resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.28.2':
|
||||
resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.2':
|
||||
resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.2':
|
||||
resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.2':
|
||||
resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.28.2':
|
||||
resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.28.2':
|
||||
resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.2':
|
||||
resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.28.2':
|
||||
resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.28.2':
|
||||
resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.28.2':
|
||||
resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.28.2':
|
||||
resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@hono/node-server@2.1.1':
|
||||
resolution: {integrity: sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -202,6 +361,11 @@ packages:
|
||||
resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild@0.28.2:
|
||||
resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
escape-html@1.0.3:
|
||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||
|
||||
@@ -491,6 +655,84 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.28.2':
|
||||
optional: true
|
||||
|
||||
'@hono/node-server@2.1.1(hono@4.13.9)':
|
||||
dependencies:
|
||||
hono: 4.13.9
|
||||
@@ -616,6 +858,35 @@ snapshots:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
esbuild@0.28.2:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.28.2
|
||||
'@esbuild/android-arm': 0.28.2
|
||||
'@esbuild/android-arm64': 0.28.2
|
||||
'@esbuild/android-x64': 0.28.2
|
||||
'@esbuild/darwin-arm64': 0.28.2
|
||||
'@esbuild/darwin-x64': 0.28.2
|
||||
'@esbuild/freebsd-arm64': 0.28.2
|
||||
'@esbuild/freebsd-x64': 0.28.2
|
||||
'@esbuild/linux-arm': 0.28.2
|
||||
'@esbuild/linux-arm64': 0.28.2
|
||||
'@esbuild/linux-ia32': 0.28.2
|
||||
'@esbuild/linux-loong64': 0.28.2
|
||||
'@esbuild/linux-mips64el': 0.28.2
|
||||
'@esbuild/linux-ppc64': 0.28.2
|
||||
'@esbuild/linux-riscv64': 0.28.2
|
||||
'@esbuild/linux-s390x': 0.28.2
|
||||
'@esbuild/linux-x64': 0.28.2
|
||||
'@esbuild/netbsd-arm64': 0.28.2
|
||||
'@esbuild/netbsd-x64': 0.28.2
|
||||
'@esbuild/openbsd-arm64': 0.28.2
|
||||
'@esbuild/openbsd-x64': 0.28.2
|
||||
'@esbuild/openharmony-arm64': 0.28.2
|
||||
'@esbuild/sunos-x64': 0.28.2
|
||||
'@esbuild/win32-arm64': 0.28.2
|
||||
'@esbuild/win32-ia32': 0.28.2
|
||||
'@esbuild/win32-x64': 0.28.2
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
|
||||
etag@1.8.1: {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
packages:
|
||||
- 'packages/*'
|
||||
- 'apps/*'
|
||||
allowBuilds:
|
||||
esbuild: set this to true or false
|
||||
+29
-17
@@ -48,29 +48,42 @@ if (-not $isAdmin) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 2. Check Node.js
|
||||
Write-Step "Checking Node.js..."
|
||||
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
|
||||
if (-not $nodeCmd) {
|
||||
Write-Err "Node.js not found. Install Node.js 22+ from https://nodejs.org"
|
||||
exit 1
|
||||
# 2. Locate runtime (bundled portable package first, else system Node.js + repo build)
|
||||
Write-Step "Locating runtime..."
|
||||
$bundledNode = Join-Path $PSScriptRoot "node.exe"
|
||||
$bundledAgent = Join-Path $PSScriptRoot "agent.mjs"
|
||||
|
||||
if ((Test-Path $bundledNode) -and (Test-Path $bundledAgent)) {
|
||||
# 便携包:使用包内运行时与被打包好的被控端,无需本机安装 Node.js
|
||||
$nodeExe = $bundledNode
|
||||
$agentJs = $bundledAgent
|
||||
if (-not $ProjectRoot) { $ProjectRoot = $PSScriptRoot }
|
||||
Write-Ok "Using bundled runtime (portable package)"
|
||||
} else {
|
||||
# 开发模式:系统 Node.js + 仓库代码
|
||||
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
|
||||
if (-not $nodeCmd) {
|
||||
Write-Err "Node.js not found. Install Node.js 22+ from https://nodejs.org"
|
||||
exit 1
|
||||
}
|
||||
$nodeExe = $nodeCmd.Source
|
||||
if (-not $ProjectRoot) { $ProjectRoot = Split-Path -Parent $PSScriptRoot }
|
||||
$agentJs = Join-Path $ProjectRoot "apps\agent\dist\index.js"
|
||||
if (-not (Test-Path $agentJs)) {
|
||||
Write-Err "Agent build not found: $agentJs"
|
||||
Write-Warn "Run 'pnpm install' and 'pnpm build' in the repo root first."
|
||||
exit 1
|
||||
}
|
||||
Write-Ok "Using system Node.js"
|
||||
}
|
||||
$ver = (& node --version).TrimStart('v')
|
||||
|
||||
$ver = (& $nodeExe --version).TrimStart('v')
|
||||
$major = [int]($ver.Split('.')[0])
|
||||
if ($major -lt 22) {
|
||||
Write-Err "Node.js 22+ required, found v$ver"
|
||||
exit 1
|
||||
}
|
||||
Write-Ok "Node.js v$ver"
|
||||
|
||||
# 3. Locate the built agent
|
||||
if (-not $ProjectRoot) { $ProjectRoot = Split-Path -Parent $PSScriptRoot }
|
||||
$agentJs = Join-Path $ProjectRoot "apps\agent\dist\index.js"
|
||||
if (-not (Test-Path $agentJs)) {
|
||||
Write-Err "Agent build not found: $agentJs"
|
||||
Write-Warn "Run 'pnpm install' and 'pnpm build' in the repo root first."
|
||||
exit 1
|
||||
}
|
||||
Write-Ok "Agent entry: $agentJs"
|
||||
|
||||
# 4. Config + pre-shared key
|
||||
@@ -116,7 +129,6 @@ Write-Ok "Inbound rule allowed on TCP $Port"
|
||||
# 6. Scheduled task (auto start on logon, highest privileges)
|
||||
Write-Step "Registering scheduled task..."
|
||||
$taskName = "nodeagent"
|
||||
$nodeExe = $nodeCmd.Source
|
||||
$action = New-ScheduledTaskAction -Execute $nodeExe -Argument "`"$agentJs`"" -WorkingDirectory $ProjectRoot
|
||||
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries `
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 构建 Windows 便携安装包。
|
||||
*
|
||||
* 用法: node scripts/pack.mjs [--node v22.20.0] [--out release]
|
||||
*
|
||||
* 产物: <out>/nodeagent-win-x64.zip
|
||||
* ├── node.exe Node.js 运行时(免装 Node.js)
|
||||
* ├── agent.mjs esbuild 打包的被控端(含全部依赖)
|
||||
* ├── install.ps1 一键安装
|
||||
* └── uninstall.ps1 一键卸载
|
||||
*/
|
||||
import { execFileSync, execSync } from 'node:child_process';
|
||||
import { copyFileSync, createWriteStream, existsSync, mkdirSync, rmSync } from 'node:fs';
|
||||
import { get } from 'node:https';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(__dirname, '..');
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const getArg = (k, d) => {
|
||||
const i = args.indexOf(k);
|
||||
return i >= 0 && args[i + 1] ? args[i + 1] : d;
|
||||
};
|
||||
|
||||
const NODE_VERSION = getArg('--node', 'v22.20.0');
|
||||
const OUT_DIR = getArg('--out', join(root, 'release'));
|
||||
const PKG_DIR = join(OUT_DIR, 'nodeagent-win-x64');
|
||||
const MIRROR = process.env.NODEAGENT_NODE_MIRROR ?? 'https://npmmirror.com/mirrors/node';
|
||||
const NODE_ZIP_URL = `${MIRROR}/${NODE_VERSION}/node-${NODE_VERSION}-win-x64.zip`;
|
||||
|
||||
const log = (msg) => console.log(msg);
|
||||
const fail = (msg) => {
|
||||
console.error(`✗ ${msg}`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
async function download(url, dest) {
|
||||
log(` 下载 ${url}`);
|
||||
return new Promise((resolve, reject) => {
|
||||
const follow = (u, redirects = 0) => {
|
||||
get(u, (res) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if (redirects > 5) return reject(new Error('重定向过多'));
|
||||
return follow(res.headers.location, redirects + 1);
|
||||
}
|
||||
if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
|
||||
const file = createWriteStream(dest);
|
||||
res.pipe(file);
|
||||
file.on('finish', () => file.close(() => resolve()));
|
||||
file.on('error', reject);
|
||||
}).on('error', reject);
|
||||
};
|
||||
follow(url);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
log('=== ① 构建 workspace ===');
|
||||
execSync('pnpm -r build', { cwd: root, stdio: 'inherit' });
|
||||
|
||||
log('\n=== ② esbuild 打包被控端 ===');
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
const bundleOut = join(OUT_DIR, 'agent.mjs');
|
||||
const esbuild = join(root, 'node_modules', '.bin', 'esbuild');
|
||||
execFileSync(
|
||||
esbuild,
|
||||
[
|
||||
'apps/agent/dist/index.js',
|
||||
'--bundle',
|
||||
'--platform=node',
|
||||
'--target=node22',
|
||||
'--format=esm',
|
||||
'--banner:js=import { createRequire } from "node:module"; const require = createRequire(import.meta.url);',
|
||||
`--outfile=${bundleOut}`,
|
||||
],
|
||||
{ stdio: 'inherit' },
|
||||
);
|
||||
|
||||
log('\n=== ③ 下载 Node.js Windows 运行时 ===');
|
||||
const tmpZip = join(OUT_DIR, 'node-runtime.zip');
|
||||
if (existsSync(tmpZip)) {
|
||||
log(' 已缓存,跳过下载');
|
||||
} else {
|
||||
await download(NODE_ZIP_URL, tmpZip);
|
||||
}
|
||||
|
||||
log('\n=== ④ 组装便携包 ===');
|
||||
rmSync(PKG_DIR, { recursive: true, force: true });
|
||||
mkdirSync(PKG_DIR, { recursive: true });
|
||||
execSync(`unzip -o -j "${tmpZip}" "*/node.exe" -d "${PKG_DIR}"`, { stdio: 'inherit' });
|
||||
copyFileSync(bundleOut, join(PKG_DIR, 'agent.mjs'));
|
||||
copyFileSync(join(root, 'scripts', 'install.ps1'), join(PKG_DIR, 'install.ps1'));
|
||||
copyFileSync(join(root, 'scripts', 'uninstall.ps1'), join(PKG_DIR, 'uninstall.ps1'));
|
||||
const files = execSync(`ls -la "${PKG_DIR}"`, { encoding: 'utf8' });
|
||||
log(files.split('\n').slice(0, 8).join('\n'));
|
||||
|
||||
log('\n=== ⑤ 打 zip ===');
|
||||
const zipOut = join(OUT_DIR, 'nodeagent-win-x64.zip');
|
||||
rmSync(zipOut, { force: true });
|
||||
execSync(`cd "${PKG_DIR}" && zip -q -r "${zipOut}" .`, { stdio: 'inherit' });
|
||||
|
||||
const size = execSync(`du -sh "${zipOut}"`, { encoding: 'utf8' }).split('\t')[0];
|
||||
log(`\n✓ 完成: ${zipOut}(${size.trim()})`);
|
||||
log(' 分发方式:解压后右键以管理员运行 install.ps1 即可');
|
||||
}
|
||||
|
||||
try {
|
||||
await main();
|
||||
} catch (err) {
|
||||
fail(err instanceof Error ? err.message : String(err));
|
||||
}
|
||||
Reference in new issue
Block a user