easytouch-windows 2.0.2 → 2.0.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/README.md +39 -60
- package/SKILL.md +18 -27
- package/bin/{arm64/et.exe → et_arm64.exe} +0 -0
- package/bin/{x64/et.exe → et_x64.exe} +0 -0
- package/init.js +218 -22
- package/package.json +4 -2
- package/bin/et.js +0 -60
package/README.md
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
目前支持以下操作系统的 x64 和 ARM64 两种 CPU 架构:
|
|
8
8
|
|
|
9
9
|
- [x] Windows
|
|
10
|
-
|
|
11
10
|
- [x] Linux
|
|
12
11
|
- [x] MACOS(目前缺少设备验证功能)
|
|
13
12
|
|
|
@@ -35,34 +34,40 @@
|
|
|
35
34
|
|
|
36
35
|
### 安装
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
推荐安装带初始化 helper 的聚合包;如果你只想安装当前系统,也可以直接安装对应平台包:
|
|
39
38
|
|
|
40
39
|
```bash
|
|
41
|
-
#
|
|
40
|
+
# 推荐:聚合包,执行 easytouch init 生成 et
|
|
42
41
|
npm i -g @whuanle/easytouch
|
|
43
42
|
|
|
44
|
-
#
|
|
43
|
+
# 只安装当前系统的平台包
|
|
45
44
|
npm i -g easytouch-windows
|
|
46
|
-
|
|
47
|
-
# Linux
|
|
48
45
|
npm i -g easytouch-linux
|
|
49
|
-
|
|
50
|
-
# macOS
|
|
51
46
|
npm i -g easytouch-macos
|
|
52
47
|
```
|
|
53
48
|
|
|
49
|
+
`@whuanle/easytouch` 会在包内直接附带 Windows、Linux、macOS 的 x64 和 arm64 原生二进制。执行 `easytouch init` 后,会按当前主机平台和 CPU 架构复制出真正可直接调用的 `et` 文件。
|
|
54
50
|
|
|
51
|
+
初始化命令:
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
```bash
|
|
54
|
+
# 聚合包
|
|
55
|
+
easytouch init
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
# 只安装当前系统的平台包时
|
|
58
|
+
easytouch-windows init
|
|
59
|
+
easytouch-linux init
|
|
60
|
+
easytouch-macos init
|
|
61
|
+
```
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
`init` 默认会把原生文件写回安装包目录,并同步刷新 `et` 命令入口。
|
|
61
64
|
|
|
62
65
|
|
|
63
66
|
|
|
64
67
|
### 使用示例
|
|
65
68
|
|
|
69
|
+
以下示例假设你已经通过 `init` 生成好了原生 `et`:
|
|
70
|
+
|
|
66
71
|
截取屏幕。
|
|
67
72
|
|
|
68
73
|
```
|
|
@@ -107,82 +112,56 @@ npx skills add https://github.com/whuanle/EasyTouch
|
|
|
107
112
|
|
|
108
113
|
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
**全局安装后(推荐)**
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
如果你已经全局安装了聚合包,可以直接使用 helper 命令生成原生 `et`:
|
|
113
118
|
|
|
114
119
|
```bash
|
|
115
|
-
npm i @whuanle/easytouch
|
|
116
|
-
|
|
120
|
+
npm i -g @whuanle/easytouch
|
|
121
|
+
easytouch init
|
|
117
122
|
```
|
|
118
123
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
执行后会生成:
|
|
122
|
-
|
|
123
|
-
- Windows:`./node_modules/@whuanle/easytouch/et.exe`
|
|
124
|
-
- Linux / macOS:`./node_modules/@whuanle/easytouch/et`
|
|
124
|
+
默认会把 `et` 生成到全局安装目录下的包目录里,并同步刷新全局 `et` 命令。
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
默认路径通常是:
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"mcpServers": {
|
|
131
|
-
"easytouch": {
|
|
132
|
-
"command": "<你的项目路径>/node_modules/@whuanle/easytouch/et",
|
|
133
|
-
"args": ["mcp-stdio"]
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
```
|
|
128
|
+
- Windows:`<npm root -g>/@whuanle/easytouch/et.exe`
|
|
129
|
+
- Linux / macOS:`<npm root -g>/@whuanle/easytouch/et`
|
|
138
130
|
|
|
139
|
-
|
|
131
|
+
全局命令入口通常是:
|
|
140
132
|
|
|
141
|
-
|
|
133
|
+
- Windows:`<npm prefix -g>/et.cmd`
|
|
134
|
+
- Linux / macOS:`<npm prefix -g>/bin/et`
|
|
142
135
|
|
|
143
|
-
|
|
136
|
+
如果需要查看你自己机器上的真实路径,可以执行:
|
|
144
137
|
|
|
145
138
|
```bash
|
|
146
|
-
npm
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```json
|
|
150
|
-
{
|
|
151
|
-
"mcpServers": {
|
|
152
|
-
"easytouch": {
|
|
153
|
-
"command": "et",
|
|
154
|
-
"args": ["mcp-stdio"]
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
139
|
+
npm root -g
|
|
140
|
+
npm prefix -g
|
|
158
141
|
```
|
|
159
142
|
|
|
160
|
-
|
|
143
|
+
也可以显式指定输出位置:
|
|
161
144
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
**不想初始化原生文件时(备用)**
|
|
145
|
+
```bash
|
|
146
|
+
easytouch init --output <你想放置 et 的路径>
|
|
147
|
+
```
|
|
166
148
|
|
|
167
|
-
|
|
149
|
+
如果你安装的是平台包,初始化命令分别是 `easytouch-windows init`、`easytouch-linux init`、`easytouch-macos init`。
|
|
168
150
|
|
|
169
|
-
|
|
170
|
-
- Linux / macOS:`command` 写 `npx`
|
|
151
|
+
生成完原生文件后,MCP 直接调用这个文件即可:
|
|
171
152
|
|
|
172
153
|
```json
|
|
173
154
|
{
|
|
174
155
|
"mcpServers": {
|
|
175
156
|
"easytouch": {
|
|
176
|
-
"command": "
|
|
177
|
-
"args": ["
|
|
157
|
+
"command": "et",
|
|
158
|
+
"args": ["mcp-stdio"]
|
|
178
159
|
}
|
|
179
160
|
}
|
|
180
161
|
}
|
|
181
162
|
```
|
|
182
163
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Linux / macOS 如果使用这段备用配置,把 `command` 改回 `npx` 即可。
|
|
164
|
+
如果宿主程序不走 PATH,再改成 `npm prefix -g` 或 `npm root -g` 对应的实际路径。
|
|
186
165
|
|
|
187
166
|
### 语义元素定位
|
|
188
167
|
|
package/SKILL.md
CHANGED
|
@@ -364,19 +364,23 @@ et mcp-stdio --output json
|
|
|
364
364
|
|
|
365
365
|
### 配置示例
|
|
366
366
|
|
|
367
|
-
|
|
367
|
+
优先在全局安装后执行 `init`,把真实原生 `et` 程序复制出来,再让 MCP 直接调用这个文件:
|
|
368
368
|
|
|
369
369
|
```bash
|
|
370
|
-
npm i @whuanle/easytouch
|
|
371
|
-
|
|
370
|
+
npm i -g @whuanle/easytouch
|
|
371
|
+
easytouch init
|
|
372
372
|
```
|
|
373
373
|
|
|
374
|
-
|
|
374
|
+
这一步会直接从包内复制当前主机对应的原生 `et` 文件。
|
|
375
375
|
|
|
376
376
|
生成后的默认路径:
|
|
377
377
|
|
|
378
|
-
- Windows
|
|
379
|
-
- Linux / macOS
|
|
378
|
+
- Windows:`<npm root -g>/@whuanle/easytouch/et.exe`
|
|
379
|
+
- Linux / macOS:`<npm root -g>/@whuanle/easytouch/et`
|
|
380
|
+
|
|
381
|
+
同时会刷新全局 `et` 命令。
|
|
382
|
+
|
|
383
|
+
也可以通过 `--output` 指定输出位置。
|
|
380
384
|
|
|
381
385
|
推荐配置:
|
|
382
386
|
|
|
@@ -384,7 +388,7 @@ node ./node_modules/@whuanle/easytouch/init.js
|
|
|
384
388
|
{
|
|
385
389
|
"mcpServers": {
|
|
386
390
|
"easytouch": {
|
|
387
|
-
"command": "
|
|
391
|
+
"command": "et",
|
|
388
392
|
"args": ["mcp-stdio"]
|
|
389
393
|
}
|
|
390
394
|
}
|
|
@@ -393,30 +397,17 @@ node ./node_modules/@whuanle/easytouch/init.js
|
|
|
393
397
|
|
|
394
398
|
Windows 请把文件名写成 `et.exe`。Linux / macOS 写 `et`。
|
|
395
399
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
如果宿主程序不能从 PATH 找到命令,旧方式仍可用:
|
|
399
|
-
|
|
400
|
-
- Windows:把 `command` 改成 `C:\Users\<你自己的用户名>\AppData\Roaming\npm\et.cmd`
|
|
401
|
-
- Linux / macOS:先执行 `npm prefix -g`,再把 `command` 改成 `<prefix>/bin/et`
|
|
400
|
+
默认会把 `et` 生成到全局安装目录下的包目录里,并同步刷新全局 `et` 命令。也可以显式指定输出路径:
|
|
402
401
|
|
|
403
|
-
|
|
402
|
+
```bash
|
|
403
|
+
easytouch init --output <你想放置 et 的路径>
|
|
404
|
+
```
|
|
404
405
|
|
|
405
|
-
|
|
406
|
-
- Linux / macOS:`command` 写 `npx`
|
|
406
|
+
如果你直接安装的是平台包,初始化命令分别是 `easytouch-windows init`、`easytouch-linux init`、`easytouch-macos init`。
|
|
407
407
|
|
|
408
|
-
|
|
409
|
-
{
|
|
410
|
-
"mcpServers": {
|
|
411
|
-
"easytouch": {
|
|
412
|
-
"command": "npx.cmd",
|
|
413
|
-
"args": ["-y", "@whuanle/easytouch", "mcp-stdio"]
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
```
|
|
408
|
+
如果需要查看实际路径,可以执行 `npm root -g` 和 `npm prefix -g`。
|
|
418
409
|
|
|
419
|
-
|
|
410
|
+
如果宿主能正确处理 PATH,MCP 直接写 `command: "et"` 即可;否则改成 `npm prefix -g` 或 `npm root -g` 对应的实际路径。
|
|
420
411
|
|
|
421
412
|
如果 Windows 宿主报 `LOCAL_PROCESS_ERROR`,优先改用 `init.js` 生成的 `et.exe`;如果仍走 npm 命令,再检查这里是不是还写成了 `npx`。
|
|
422
413
|
|
|
Binary file
|
|
Binary file
|
package/init.js
CHANGED
|
@@ -3,19 +3,23 @@
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const helperCommandName = "easytouch-windows";
|
|
7
|
+
const generatedCommandName = "et";
|
|
8
|
+
|
|
9
|
+
const supportedArchitectures = new Set(["x64", "arm64"]);
|
|
10
10
|
|
|
11
11
|
function printUsage() {
|
|
12
12
|
process.stdout.write(
|
|
13
13
|
[
|
|
14
14
|
"Usage:",
|
|
15
|
-
"
|
|
15
|
+
" easytouch-windows init [--output <path>] [--force]",
|
|
16
|
+
" npx easytouch-windows init [--output <path>] [--force]",
|
|
17
|
+
" node init.js [init] [--output <path>] [--force]",
|
|
16
18
|
"",
|
|
17
19
|
"Behavior:",
|
|
18
|
-
" Copies the current Windows binary
|
|
20
|
+
" Copies the current Windows binary out of this package as 'et.exe' by default.",
|
|
21
|
+
" By default, writes into this package directory.",
|
|
22
|
+
" When installed through npm, also refreshes the 'et' command if possible.",
|
|
19
23
|
" Use --output to write to a different file or directory.",
|
|
20
24
|
].join("\n") + "\n"
|
|
21
25
|
);
|
|
@@ -26,7 +30,16 @@ function fail(message) {
|
|
|
26
30
|
process.exit(1);
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
function
|
|
33
|
+
function normalizeArgs(argv) {
|
|
34
|
+
if (argv[0] === "init") {
|
|
35
|
+
return argv.slice(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return argv;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function parseArgs(rawArgv) {
|
|
42
|
+
const argv = normalizeArgs(rawArgv);
|
|
30
43
|
let output = null;
|
|
31
44
|
let force = false;
|
|
32
45
|
|
|
@@ -54,11 +67,11 @@ function parseArgs(argv) {
|
|
|
54
67
|
return { output, force };
|
|
55
68
|
}
|
|
56
69
|
|
|
57
|
-
function
|
|
70
|
+
function getAvailableBinaries() {
|
|
58
71
|
try {
|
|
59
72
|
return fs
|
|
60
73
|
.readdirSync(path.join(__dirname, "bin"), { withFileTypes: true })
|
|
61
|
-
.filter((entry) => entry.
|
|
74
|
+
.filter((entry) => entry.isFile() && entry.name.startsWith("et_"))
|
|
62
75
|
.map((entry) => entry.name)
|
|
63
76
|
.sort();
|
|
64
77
|
} catch {
|
|
@@ -66,28 +79,36 @@ function getAvailableArchitectures() {
|
|
|
66
79
|
}
|
|
67
80
|
}
|
|
68
81
|
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
fail(`Unsupported architecture '${process.arch}' on platform '${process.platform}'.`);
|
|
82
|
+
function binaryNameForArch(arch = process.arch) {
|
|
83
|
+
if (!supportedArchitectures.has(arch)) {
|
|
84
|
+
fail(`Unsupported architecture '${arch}' on platform '${process.platform}'.`);
|
|
73
85
|
}
|
|
74
86
|
|
|
75
|
-
|
|
87
|
+
return `et_${arch}.exe`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function resolveBinaryPath() {
|
|
91
|
+
const fileName = binaryNameForArch();
|
|
92
|
+
const sourcePath = path.join(__dirname, "bin", fileName);
|
|
76
93
|
if (!fs.existsSync(sourcePath)) {
|
|
77
|
-
const
|
|
78
|
-
const availableMessage =
|
|
79
|
-
? ` Available
|
|
94
|
+
const availableBinaries = getAvailableBinaries();
|
|
95
|
+
const availableMessage = availableBinaries.length
|
|
96
|
+
? ` Available binaries: ${availableBinaries.join(", ")}.`
|
|
80
97
|
: "";
|
|
81
|
-
fail(`The package is missing '
|
|
98
|
+
fail(`The package is missing '${fileName}' for architecture '${process.arch}'.${availableMessage}`);
|
|
82
99
|
}
|
|
83
100
|
|
|
84
101
|
return sourcePath;
|
|
85
102
|
}
|
|
86
103
|
|
|
104
|
+
function defaultOutputPath() {
|
|
105
|
+
return path.join(__dirname, "et.exe");
|
|
106
|
+
}
|
|
107
|
+
|
|
87
108
|
function resolveOutputPath(requestedOutput) {
|
|
88
109
|
let outputPath = requestedOutput
|
|
89
110
|
? path.resolve(process.cwd(), requestedOutput)
|
|
90
|
-
:
|
|
111
|
+
: defaultOutputPath();
|
|
91
112
|
|
|
92
113
|
if (fs.existsSync(outputPath)) {
|
|
93
114
|
const stat = fs.statSync(outputPath);
|
|
@@ -103,6 +124,22 @@ function resolveOutputPath(requestedOutput) {
|
|
|
103
124
|
return outputPath;
|
|
104
125
|
}
|
|
105
126
|
|
|
127
|
+
function filesAreIdentical(leftPath, rightPath) {
|
|
128
|
+
try {
|
|
129
|
+
const leftStat = fs.statSync(leftPath);
|
|
130
|
+
const rightStat = fs.statSync(rightPath);
|
|
131
|
+
if (leftStat.size !== rightStat.size) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const leftContent = fs.readFileSync(leftPath);
|
|
136
|
+
const rightContent = fs.readFileSync(rightPath);
|
|
137
|
+
return leftContent.equals(rightContent);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
106
143
|
function initializeBinary(sourcePath, destinationPath, force) {
|
|
107
144
|
const resolvedSource = path.resolve(sourcePath);
|
|
108
145
|
const resolvedDestination = path.resolve(destinationPath);
|
|
@@ -111,8 +148,15 @@ function initializeBinary(sourcePath, destinationPath, force) {
|
|
|
111
148
|
return;
|
|
112
149
|
}
|
|
113
150
|
|
|
114
|
-
if (fs.existsSync(resolvedDestination)
|
|
115
|
-
|
|
151
|
+
if (fs.existsSync(resolvedDestination)) {
|
|
152
|
+
if (filesAreIdentical(resolvedSource, resolvedDestination)) {
|
|
153
|
+
process.stdout.write(`et init: binary already available at ${resolvedDestination}\n`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!force) {
|
|
158
|
+
fail(`Destination '${resolvedDestination}' already exists. Use --force to overwrite it.`);
|
|
159
|
+
}
|
|
116
160
|
}
|
|
117
161
|
|
|
118
162
|
fs.mkdirSync(path.dirname(resolvedDestination), { recursive: true });
|
|
@@ -120,5 +164,157 @@ function initializeBinary(sourcePath, destinationPath, force) {
|
|
|
120
164
|
process.stdout.write(`et init: copied ${resolvedSource} -> ${resolvedDestination}\n`);
|
|
121
165
|
}
|
|
122
166
|
|
|
167
|
+
function findNodeModulesRoot(startDir) {
|
|
168
|
+
let current = path.resolve(startDir);
|
|
169
|
+
|
|
170
|
+
while (true) {
|
|
171
|
+
if (path.basename(current) === "node_modules") {
|
|
172
|
+
return current;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const parent = path.dirname(current);
|
|
176
|
+
if (parent === current) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
current = parent;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function commandFileCandidates(commandName) {
|
|
184
|
+
return [`${commandName}.cmd`, `${commandName}.ps1`, commandName];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function uniquePaths(paths) {
|
|
188
|
+
return [...new Set(paths.filter(Boolean).map((entry) => path.resolve(entry)))];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function resolveCommandBinDir(startDir, commandName) {
|
|
192
|
+
const nodeModulesRoot = findNodeModulesRoot(startDir);
|
|
193
|
+
if (!nodeModulesRoot) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const installRoot = path.dirname(nodeModulesRoot);
|
|
198
|
+
const candidates = uniquePaths([path.join(nodeModulesRoot, ".bin"), installRoot]);
|
|
199
|
+
|
|
200
|
+
for (const candidate of candidates) {
|
|
201
|
+
for (const fileName of commandFileCandidates(commandName)) {
|
|
202
|
+
if (fs.existsSync(path.join(candidate, fileName))) {
|
|
203
|
+
return candidate;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
for (const candidate of candidates) {
|
|
209
|
+
if (fs.existsSync(candidate)) {
|
|
210
|
+
return candidate;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function managedCommandMarker() {
|
|
218
|
+
return "EasyTouch generated by init";
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function readTextFile(filePath) {
|
|
222
|
+
try {
|
|
223
|
+
return fs.readFileSync(filePath, "utf8");
|
|
224
|
+
} catch {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function assertManagedCommandTarget(filePath, force) {
|
|
230
|
+
if (!fs.existsSync(filePath)) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const content = readTextFile(filePath);
|
|
235
|
+
if (content && content.includes(managedCommandMarker())) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!force) {
|
|
240
|
+
fail(`Command '${filePath}' already exists. Use --force to overwrite it.`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function writeManagedCommand(filePath, content, force, executable) {
|
|
245
|
+
assertManagedCommandTarget(filePath, force);
|
|
246
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
247
|
+
fs.writeFileSync(filePath, content, "utf8");
|
|
248
|
+
if (executable) {
|
|
249
|
+
fs.chmodSync(filePath, 0o755);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function escapeForSingleQuotedPowerShell(value) {
|
|
254
|
+
return value.replace(/'/g, "''");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function relativeShellPath(fromDir, toFile) {
|
|
258
|
+
return path.relative(fromDir, toFile).split(path.sep).join("/");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function installGeneratedCommand(targetBinaryPath, force) {
|
|
262
|
+
const binDir = resolveCommandBinDir(__dirname, helperCommandName);
|
|
263
|
+
if (!binDir) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const resolvedTarget = path.resolve(targetBinaryPath);
|
|
268
|
+
const relativeWindowsPath = path.relative(binDir, resolvedTarget);
|
|
269
|
+
const relativePosixPath = relativeShellPath(binDir, resolvedTarget);
|
|
270
|
+
|
|
271
|
+
writeManagedCommand(
|
|
272
|
+
path.join(binDir, generatedCommandName),
|
|
273
|
+
[
|
|
274
|
+
"#!/bin/sh",
|
|
275
|
+
`# ${managedCommandMarker()}`,
|
|
276
|
+
'basedir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)',
|
|
277
|
+
`exec "$basedir/${relativePosixPath}" "$@"`,
|
|
278
|
+
"",
|
|
279
|
+
].join("\n"),
|
|
280
|
+
force,
|
|
281
|
+
true
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
writeManagedCommand(
|
|
285
|
+
path.join(binDir, `${generatedCommandName}.cmd`),
|
|
286
|
+
[
|
|
287
|
+
"@ECHO off",
|
|
288
|
+
`:: ${managedCommandMarker()}`,
|
|
289
|
+
"SETLOCAL",
|
|
290
|
+
`SET \"_ET_TARGET=%~dp0${relativeWindowsPath}\"`,
|
|
291
|
+
'"%_ET_TARGET%" %*',
|
|
292
|
+
"",
|
|
293
|
+
].join("\r\n"),
|
|
294
|
+
force,
|
|
295
|
+
false
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
writeManagedCommand(
|
|
299
|
+
path.join(binDir, `${generatedCommandName}.ps1`),
|
|
300
|
+
[
|
|
301
|
+
`# ${managedCommandMarker()}`,
|
|
302
|
+
`$target = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot '${escapeForSingleQuotedPowerShell(relativeWindowsPath)}'))`,
|
|
303
|
+
"& $target @args",
|
|
304
|
+
"exit $LASTEXITCODE",
|
|
305
|
+
"",
|
|
306
|
+
].join("\r\n"),
|
|
307
|
+
force,
|
|
308
|
+
false
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
process.stdout.write(`et init: updated command '${generatedCommandName}' in ${binDir}\n`);
|
|
312
|
+
}
|
|
313
|
+
|
|
123
314
|
const options = parseArgs(process.argv.slice(2));
|
|
124
|
-
|
|
315
|
+
const outputPath = resolveOutputPath(options.output);
|
|
316
|
+
initializeBinary(resolveBinaryPath(), outputPath, options.force);
|
|
317
|
+
|
|
318
|
+
if (path.resolve(outputPath) === path.resolve(defaultOutputPath())) {
|
|
319
|
+
installGeneratedCommand(outputPath, options.force);
|
|
320
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "easytouch-windows",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "Windows binary distribution for EasyTouch with x64 and arm64 binaries.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"homepage": "https://github.com/whuanle/EasyTouch#readme",
|
|
15
15
|
"bin": {
|
|
16
|
-
"
|
|
16
|
+
"easytouch-windows": "init.js",
|
|
17
|
+
"et_x64": "bin/et_x64.exe",
|
|
18
|
+
"et_arm64": "bin/et_arm64.exe"
|
|
17
19
|
},
|
|
18
20
|
"os": [
|
|
19
21
|
"win32"
|
package/bin/et.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const cp = require("node:child_process");
|
|
4
|
-
const fs = require("node:fs");
|
|
5
|
-
const path = require("node:path");
|
|
6
|
-
|
|
7
|
-
const archDirectoryByNodeArch = {
|
|
8
|
-
x64: "x64",
|
|
9
|
-
arm64: "arm64",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const packageName = require(path.join(__dirname, "..", "package.json")).name;
|
|
13
|
-
|
|
14
|
-
function fail(message) {
|
|
15
|
-
process.stderr.write(`et: ${message}\n`);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function getAvailableArchitectures() {
|
|
20
|
-
try {
|
|
21
|
-
return fs
|
|
22
|
-
.readdirSync(__dirname, { withFileTypes: true })
|
|
23
|
-
.filter((entry) => entry.isDirectory())
|
|
24
|
-
.map((entry) => entry.name)
|
|
25
|
-
.sort();
|
|
26
|
-
} catch {
|
|
27
|
-
return [];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function resolveBinaryPath() {
|
|
32
|
-
const archDirectory = archDirectoryByNodeArch[process.arch];
|
|
33
|
-
if (!archDirectory) {
|
|
34
|
-
fail(`Unsupported architecture '${process.arch}' on platform '${process.platform}'.`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const binaryName = process.platform === "win32" ? "et.exe" : "et";
|
|
38
|
-
const binaryPath = path.join(__dirname, archDirectory, binaryName);
|
|
39
|
-
if (!fs.existsSync(binaryPath)) {
|
|
40
|
-
const availableArchitectures = getAvailableArchitectures();
|
|
41
|
-
const availableMessage = availableArchitectures.length
|
|
42
|
-
? ` Available architectures: ${availableArchitectures.join(", ")}.`
|
|
43
|
-
: "";
|
|
44
|
-
fail(
|
|
45
|
-
`The platform package '${packageName}' is missing '${binaryName}' for architecture '${archDirectory}'.${availableMessage}`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return binaryPath;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const result = cp.spawnSync(resolveBinaryPath(), process.argv.slice(2), {
|
|
53
|
-
stdio: "inherit",
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (result.error) {
|
|
57
|
-
fail(result.error.message);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
process.exit(result.status ?? 1);
|