Skip to content

Commit 1d2da0d

Browse files
committed
fix: add init
1 parent e9fd8d3 commit 1d2da0d

File tree

14 files changed

+214
-28
lines changed

14 files changed

+214
-28
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
- run: npm run build
4141
if: ${{ steps.release.outputs.release_created }}
4242
# 增加install script
43-
- run: npm pkg set "scripts.install"="node lib/scripts/index.js"
43+
- run: npm pkg set "scripts.install"="node lib/scripts/main.js"
4444
if: ${{ steps.release.outputs.release_created }}
4545
# 删除开发依赖
4646
- run: npm pkg delete devDependencies

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,4 @@ lib
177177
dist
178178
pnpm-lock.yaml
179179
package-lock.json
180+
build

README.en.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,54 @@ This project is open-sourced under the MIT License. Thanks to the contributions
8383
- Copyright (c) 2018, Microsoft Corporation (MIT License)
8484
- Copyright (c) 2018, David Wilson (MIT License)
8585
- Copyright (c) 2018, oznu (MIT License)
86-
- Copyright (c) 2023, Homebridge (MIT License)
86+
- Copyright (c) 2023, Homebridge (MIT License)
87+
88+
## Usage Example
89+
90+
```typescript
91+
import * as os from 'node:os'
92+
import * as pty from '@karinjs/node-pty'
93+
94+
async function run () {
95+
// Optional: Check and ensure binary compatibility with current environment
96+
await pty.init()
97+
98+
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash'
99+
const ptyProcess = pty.spawn(shell, [], {
100+
name: 'xterm-color',
101+
cols: 80,
102+
rows: 30,
103+
cwd: process.env.HOME,
104+
env: process.env
105+
})
106+
107+
ptyProcess.onData((data) => {
108+
process.stdout.write(data)
109+
})
110+
111+
ptyProcess.write('ls\r')
112+
ptyProcess.resize(100, 40)
113+
ptyProcess.write('ls\r')
114+
}
115+
116+
run()
117+
```
118+
119+
## API
120+
121+
### Base API
122+
123+
This package supports all original APIs from [@homebridge/node-pty-prebuilt-multiarch](https://github.com/homebridge/node-pty-prebuilt-multiarch).
124+
125+
### Extended API
126+
127+
We've added the following new API on top of the original ones:
128+
129+
#### init()
130+
131+
The `init()` method checks if the prebuilt binary is compatible with the current Node.js/Electron environment. This method is optional and is mainly useful in the following scenarios:
132+
133+
- After switching Node.js or Electron versions, to verify compatibility
134+
- When you need to reinstall binaries compatible with the current environment
135+
136+
> Tip: If you don't want to call the init() method, you can also directly run `npx pty` to reinstall binaries compatible with the current environment.

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,53 @@ npm install @homebridge/node-pty-prebuilt-multiarch:@karinjs/node-pty
8585
- Copyright (c) 2018, oznu (MIT License)
8686
- Copyright (c) 2023, Homebridge (MIT License)
8787

88+
## 使用示例
89+
90+
```typescript
91+
import * as os from 'node:os'
92+
import * as pty from '@karinjs/node-pty'
93+
94+
async function run () {
95+
// 可选: 检查并确保二进制文件与当前环境兼容
96+
await pty.init()
97+
98+
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash'
99+
const ptyProcess = pty.spawn(shell, [], {
100+
name: 'xterm-color',
101+
cols: 80,
102+
rows: 30,
103+
cwd: process.env.HOME,
104+
env: process.env
105+
})
106+
107+
ptyProcess.onData((data) => {
108+
process.stdout.write(data)
109+
})
110+
111+
ptyProcess.write('ls\r')
112+
ptyProcess.resize(100, 40)
113+
ptyProcess.write('ls\r')
114+
}
115+
116+
run()
117+
```
118+
119+
## API
120+
121+
### 基础 API
122+
123+
本包支持 [@homebridge/node-pty-prebuilt-multiarch](https://github.com/homebridge/node-pty-prebuilt-multiarch) 的所有原有 API。
124+
125+
### 扩展 API
126+
127+
在原有基础上,我们新增了以下 API:
128+
129+
#### init()
130+
131+
`init()` 方法用于检查预编译二进制文件是否与当前 Node.js/Electron 环境兼容。该方法是可选的,主要用于以下场景:
132+
133+
- 更换 Node.js 或 Electron 版本后,需要验证兼容性
134+
- 需要重新安装适配当前环境的二进制文件
135+
136+
> 提示:如果不想调用 init() 方法,也可以直接运行 `npx pty` 来重新安装适配当前环境的二进制文件。
137+

index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict'
2+
Object.defineProperty(exports, '__esModule', { value: true })
3+
4+
const pty = require('./lib/index.js')
5+
const main = require('./lib/scripts/index.js')
6+
7+
exports.init = main.main
8+
exports.spawn = pty.spawn
9+
exports.fork = pty.fork
10+
exports.createTerminal = pty.createTerminal
11+
exports.open = pty.open
12+
exports.native = pty.native

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@karinjs/node-pty",
3-
"main": "lib/index.js",
3+
"main": "index.js",
44
"types": "lib/index.d.ts",
55
"version": "1.0.2",
66
"description": "node-pty without compilation",
@@ -23,10 +23,15 @@
2323
},
2424
"license": "MIT",
2525
"author": "shijin",
26+
"bin": {
27+
"pty": "./lib/scripts/main.js"
28+
},
2629
"scripts": {
27-
"build": "tsup --tsconfig tsconfig.json --config tsup.config.ts",
30+
"build": "tsc && tsup --tsconfig tsconfig.json --config tsup.config.ts",
2831
"download": "tsx src/index.ts",
29-
"pub": "npm publish --access public"
32+
"test:install": "tsx src/install/index.ts",
33+
"pub": "npm publish --access public",
34+
"test": "node test.mjs"
3035
},
3136
"files": [
3237
"lib",

src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ const main = async () => {
2727
const data = fs.readFileSync(dts, 'utf-8')
2828
fs.writeFileSync(
2929
path.resolve(lib, 'index.d.ts'),
30-
data.replace('@homebridge/node-pty-prebuilt-multiarch', _PKG_NAME)
31-
)
30+
data
31+
.replace('@homebridge/node-pty-prebuilt-multiarch', _PKG_NAME)
32+
.replace(new RegExp(`${_PKG_NAME}.*{.*`, 'g'), `${_PKG_NAME}' {
33+
/**
34+
* Initializes the pty module.
35+
*/
36+
export function init (): Promise<void>
37+
`))
3238

3339
/**
3440
* 递归删除lib文件夹下 后缀.map、 test.js后缀的

src/install/index.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { logger } from '../common/log'
55
import { getUrl } from './url'
66
import { getFileName } from './filename'
77
import { download, probe } from './download'
8+
import { VERSION_JSON_NAME } from '@/version'
89

910
/**
1011
* 递归创建目录
@@ -20,47 +21,78 @@ const mkdir = (dir: string) => {
2021
* 获取基本路径
2122
*/
2223
const getPath = () => {
24+
/** 根目录 */
2325
const dir = path.resolve(__dirname, '../..')
26+
/** 二进制根目录 */
2427
const build = path.resolve(dir, 'build')
28+
/** package.json路径 */
2529
const pkg = path.resolve(dir, 'package.json')
26-
27-
const release = path.resolve(build, 'Release')
28-
mkdir(release)
30+
/** 保存当前二进制文件的json路径 */
31+
const versionData = path.resolve(build, VERSION_JSON_NAME)
2932
return {
3033
dir,
3134
build,
3235
pkg,
33-
release
36+
versionData
37+
}
38+
}
39+
40+
/**
41+
* 当前版本缓存
42+
*/
43+
const version = {
44+
set: (name: string) => {
45+
const dir = getPath().versionData
46+
fs.writeFileSync(dir, JSON.stringify({ name }))
47+
},
48+
get: (): { name: string } | null => {
49+
const dir = getPath().versionData
50+
if (!fs.existsSync(dir)) {
51+
return null
52+
}
53+
return JSON.parse(fs.readFileSync(dir, 'utf-8'))
3454
}
3555
}
3656

3757
/**
3858
* 下载成功之后解压
3959
* @param data 下载的压缩包数据
4060
* @param destPath 目标路径
61+
* @param fileName 缓存文件名称
4162
*/
42-
const downloadAndUnzip = async (data: Buffer, destPath: string) => {
63+
const downloadAndUnzip = async (data: Buffer, destPath: string, fileName: string) => {
64+
mkdir(destPath)
4365
await decompress(data, destPath)
4466
logger.info('unzip Success:', destPath)
67+
68+
version.set(fileName)
4569
}
4670

4771
/**
48-
* 判断
72+
* 主函数
73+
* @param isForce 是否强制下载
74+
* @param isExit 执行完成后是否退出
4975
*/
50-
const main = async () => {
76+
export const main = async (isForce = false) => {
5177
try {
5278
const fileName = getFileName()
53-
logger.info('name:', fileName)
5479

80+
/** 判断已下载版本是否一致 */
81+
if (!isForce && version.get()?.name === fileName) {
82+
return
83+
}
84+
85+
logger.info('name:', fileName)
5586
const dir = getPath()
87+
5688
const url = getUrl(fileName)
5789

5890
if (url.custom) {
5991
logger.info('download URL:', url.custom)
6092

6193
try {
6294
const customResult = await download(url.custom)
63-
return await downloadAndUnzip(customResult, dir.dir)
95+
return await downloadAndUnzip(customResult, dir.dir, fileName)
6496
} catch {
6597
logger.error('failed to download custom binary, fallback to default')
6698
}
@@ -71,13 +103,9 @@ const main = async () => {
71103
logger.info('download URL:', target)
72104

73105
const data = await download(target)
74-
await downloadAndUnzip(data, dir.dir)
106+
await downloadAndUnzip(data, dir.dir, fileName)
75107
} catch (error) {
76108
logger.error('failed to download node-pty binary:')
77109
logger.error(error)
78-
} finally {
79-
process.exit(0)
80110
}
81111
}
82-
83-
main()

src/install/main.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env node
2+
3+
import { main } from '.'
4+
5+
async function run () {
6+
await main(true)
7+
process.exit(0)
8+
}
9+
10+
run()

src/install/url.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const getHostMirrorUrl = (pkgName: string) => {
2222
* @param fileName 文件名
2323
*/
2424
const getGithubUrl = (fileName: string) => {
25-
return `https://github.com/homebridge/${PKG_NAME}/releases/download/${VERSION}/${fileName}`
25+
return `https://github.com/homebridge/${PKG_NAME}/releases/download/v${VERSION}/${fileName}`
2626
}
2727

2828
/**

0 commit comments

Comments
 (0)