airport2 0.0.1
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/.editorconfig +24 -0
- package/.vscode/settings.json +5 -0
- package/CHANGELOG.md +10 -0
- package/Dockerfile +14 -0
- package/README.md +99 -0
- package/Todo.md +104 -0
- package/airport-docker.ts +20 -0
- package/airport.ts +41 -0
- package/bun.lock +265 -0
- package/dev.md +21 -0
- package/package.json +22 -0
- package/src/airport/__tests__/airport.test.ts +22 -0
- package/src/airport/air/pipeline.ts +28 -0
- package/src/airport/air/step.ts +60 -0
- package/src/airport/air/task.ts +34 -0
- package/src/airport/index.ts +23 -0
- package/src/airport/lib/date.ts +15 -0
- package/src/airport/lib/log.ts +9 -0
- package/src/airport/lib/remote.ts +27 -0
- package/src/airport/lib/run.ts +44 -0
- package/src/airport/types.ts +34 -0
- package/src/index.ts +1 -0
package/.editorconfig
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
indent_style = space
|
|
5
|
+
indent_size = 2
|
|
6
|
+
end_of_line = lf
|
|
7
|
+
charset = utf-8
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
semi = false
|
|
11
|
+
singleQuote = true
|
|
12
|
+
quote_type = single
|
|
13
|
+
|
|
14
|
+
[*.ts]
|
|
15
|
+
semi = false
|
|
16
|
+
|
|
17
|
+
[*.md]
|
|
18
|
+
|
|
19
|
+
[{package.json,*.yml}]
|
|
20
|
+
indent_style = space
|
|
21
|
+
indent_size = 2
|
|
22
|
+
|
|
23
|
+
[*.md]
|
|
24
|
+
trim_trailing_whitespace = false
|
package/CHANGELOG.md
ADDED
package/Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# ================================
|
|
2
|
+
# Only For Test
|
|
3
|
+
# ================================
|
|
4
|
+
FROM node:24
|
|
5
|
+
|
|
6
|
+
# Switch to the staging area
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
# Let Docker bind to port 8080
|
|
10
|
+
COPY ./src /app/src
|
|
11
|
+
|
|
12
|
+
# Start the Vapor service when the image is run, default to listening on 8080 in production environment
|
|
13
|
+
ENTRYPOINT ["ls"]
|
|
14
|
+
CMD ["-a"]
|
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Airport
|
|
2
|
+
|
|
3
|
+
使用`ts`编写`Shell`管道
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun add airport2
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## 核心架构
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Airport
|
|
13
|
+
├── Pipeline: 管理多个Task的执行流程
|
|
14
|
+
│ ├── Task 1
|
|
15
|
+
│ │ ├── Step 1
|
|
16
|
+
│ │ ├── Step 2
|
|
17
|
+
│ │ └── ...
|
|
18
|
+
│ ├── Task 2
|
|
19
|
+
│ └── ...
|
|
20
|
+
├── Run: 异步处理本地命令
|
|
21
|
+
├── Exec: 同步处理本地命令
|
|
22
|
+
└── Remote: 处理远程服务器连接和操作
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
在项目根据目录下创建`airport.ts`文件
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
bun airport.ts // 也可以将命令添加到package.json中
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Example
|
|
34
|
+
|
|
35
|
+
1、常规构建发布
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { name, version } from './package.json'
|
|
39
|
+
import { PipeLine, Task, remote, logError } from 'airport2'
|
|
40
|
+
|
|
41
|
+
const file = [name, version].join('-') + '.tgz'
|
|
42
|
+
|
|
43
|
+
const deployTask = new Task({
|
|
44
|
+
name: '部署应用',
|
|
45
|
+
steps: [
|
|
46
|
+
{
|
|
47
|
+
name: '构建项目',
|
|
48
|
+
run: [
|
|
49
|
+
'mkdir -p .cache',
|
|
50
|
+
'mv `npm pack` .cache/',
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: '发布到远程服务器',
|
|
55
|
+
async run() {
|
|
56
|
+
const ssh = remote('user@192.168.1.1')
|
|
57
|
+
const dir = (path?: string) => join('/home/user/test', path ?? '')
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
await ssh.run('rm -f', dir('latest'))
|
|
61
|
+
await ssh.run('mkdir -p', dir(version))
|
|
62
|
+
await ssh.scp(`.cache/${file}`, dir())
|
|
63
|
+
await ssh.run('tar -zxvf', dir(file), '-C', dir(version))
|
|
64
|
+
await ssh.run('ln -s', dir(version), dir('latest'))
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
logError(e)
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
PipeLine.run([deployTask])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
docker构建发布:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { name, version } from './package.json'
|
|
81
|
+
import { PipeLine, Task } from 'airport2'
|
|
82
|
+
|
|
83
|
+
// 创建部署任务
|
|
84
|
+
const deployTask = new Task({
|
|
85
|
+
name: '部署docker应用',
|
|
86
|
+
steps: [
|
|
87
|
+
{
|
|
88
|
+
name: '构建docker镜像',
|
|
89
|
+
run: [
|
|
90
|
+
`docker build -t ${name}:latest .`,
|
|
91
|
+
`docker tag ${name}:latest user/${name}:${version}`,
|
|
92
|
+
`docker push user/${name}:${version}`,
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
PipeLine.run([deployTask])
|
|
99
|
+
```
|
package/Todo.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# 需求文档:Airport任务调度系统
|
|
2
|
+
|
|
3
|
+
## 项目概述
|
|
4
|
+
Airport是一个基于TypeScript的现代化任务调度系统,支持本地和远程任务执行,采用Pipeline-Task-Step三级架构,可用于自动化部署、构建和运维流程。
|
|
5
|
+
|
|
6
|
+
## 开发计划
|
|
7
|
+
|
|
8
|
+
### 阶段一:核心架构设计与实现(已完成)
|
|
9
|
+
- ✅ 设计并实现Step类,支持命令执行和函数调用
|
|
10
|
+
- ✅ 设计并实现Task类,管理多个Step的串行执行
|
|
11
|
+
- ✅ 设计并实现Pipeline类,管理多个Task的串行执行
|
|
12
|
+
- ✅ 实现远程SSH连接功能,支持远程命令执行和文件传输
|
|
13
|
+
- ✅ 添加单元测试,确保核心功能的正确性
|
|
14
|
+
|
|
15
|
+
### 阶段二:功能完善与文档(进行中)
|
|
16
|
+
- ✅ 实现测试模式(test()方法)
|
|
17
|
+
- ✅ 添加详细的代码注释和文档
|
|
18
|
+
- ☐ 创建使用示例和教程文档
|
|
19
|
+
- ☐ 完善错误处理和日志系统
|
|
20
|
+
|
|
21
|
+
### 阶段三:系统集成与优化
|
|
22
|
+
- ☐ 实现配置文件支持
|
|
23
|
+
- ☐ 添加任务并行执行功能
|
|
24
|
+
- ☐ 实现任务重试机制
|
|
25
|
+
- ☐ 添加任务依赖管理
|
|
26
|
+
|
|
27
|
+
## 技术栈
|
|
28
|
+
- TypeScript
|
|
29
|
+
- bun(运行时和依赖管理)
|
|
30
|
+
- vitest(单元测试)
|
|
31
|
+
- zx(命令执行)
|
|
32
|
+
- ssh2(SSH远程连接)
|
|
33
|
+
- TypeScript类型系统
|
|
34
|
+
|
|
35
|
+
## 核心功能
|
|
36
|
+
1. **Pipeline流水线**:管理多个任务的串行执行
|
|
37
|
+
2. **Task任务**:包含多个步骤的执行单元
|
|
38
|
+
3. **Step步骤**:执行单个命令或函数
|
|
39
|
+
4. **远程操作**:通过SSH连接远程服务器执行命令和传输文件
|
|
40
|
+
5. **测试模式**:支持仅输出命令而不实际执行
|
|
41
|
+
|
|
42
|
+
## 补充说明:
|
|
43
|
+
|
|
44
|
+
### Step类
|
|
45
|
+
* Step.run有三种类型:`string | string[] | AnyFunction`,应该有两个私有函数来处理前两种情况,例如:
|
|
46
|
+
```ts
|
|
47
|
+
class Step {
|
|
48
|
+
private _runString()
|
|
49
|
+
private _runArray()
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
* `_runString`用于处理run值是字符串的情况
|
|
53
|
+
* `_runArray`用于处理run值是字符串数组的情况
|
|
54
|
+
* `AnyFunction`的情况,直接执行即可
|
|
55
|
+
|
|
56
|
+
## 使用示例
|
|
57
|
+
```typescript
|
|
58
|
+
import { Pipeline, Task, Step, remote } from './src/airport';
|
|
59
|
+
import { $ } from 'zx';
|
|
60
|
+
|
|
61
|
+
// 创建部署任务
|
|
62
|
+
const deployTask = new Task({
|
|
63
|
+
name: '部署应用',
|
|
64
|
+
steps: [
|
|
65
|
+
{
|
|
66
|
+
name: '构建项目',
|
|
67
|
+
run: [
|
|
68
|
+
'bun run build',
|
|
69
|
+
'bun run test'
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: '远程部署',
|
|
74
|
+
run: async () => {
|
|
75
|
+
const ssh = remote({
|
|
76
|
+
ssh: 'root@192.168.1.1',
|
|
77
|
+
port: 22,
|
|
78
|
+
private: '$HOME/.ssh/id_rsa'
|
|
79
|
+
});
|
|
80
|
+
await ssh.connect();
|
|
81
|
+
await ssh.run('mkdir -p /data/app');
|
|
82
|
+
await ssh.scp('dist/*', '/data/app/');
|
|
83
|
+
await ssh.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 执行流水线
|
|
90
|
+
const pipeline = new Pipeline([deployTask]);
|
|
91
|
+
await pipeline.run();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 单元测试
|
|
95
|
+
已实现核心功能的单元测试,可通过以下命令执行:
|
|
96
|
+
```bash
|
|
97
|
+
bun test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 下一步计划
|
|
101
|
+
1. 完善测试覆盖率,添加更多边界情况测试
|
|
102
|
+
2. 实现dev.md文档,详细记录开发过程和架构设计
|
|
103
|
+
3. 添加CHANGELOG.md文件记录版本更新历史
|
|
104
|
+
4. 优化错误处理和日志系统
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { name, version } from './package.json'
|
|
2
|
+
import { PipeLine, Task } from './src/airport'
|
|
3
|
+
|
|
4
|
+
// 创建部署任务
|
|
5
|
+
const deployTask = new Task({
|
|
6
|
+
name: '部署docker应用',
|
|
7
|
+
steps: [
|
|
8
|
+
{
|
|
9
|
+
name: '构建docker镜像',
|
|
10
|
+
run: [
|
|
11
|
+
`docker build -t ${name}:latest .`,
|
|
12
|
+
`docker tag ${name}:latest user/${name}:${version}`,
|
|
13
|
+
`docker push user/${name}:${version}`,
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// 执行流水线
|
|
20
|
+
PipeLine.run([deployTask])
|
package/airport.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { join } from 'path'
|
|
2
|
+
import { name, version } from './package.json'
|
|
3
|
+
import { PipeLine, Task, remote, exec, logError } from './src/airport'
|
|
4
|
+
|
|
5
|
+
const file = [name, version].join('-') + '.tgz'
|
|
6
|
+
|
|
7
|
+
// 创建部署任务
|
|
8
|
+
const deployTask = new Task({
|
|
9
|
+
name: '部署应用',
|
|
10
|
+
steps: [
|
|
11
|
+
{
|
|
12
|
+
name: '构建项目',
|
|
13
|
+
run: [
|
|
14
|
+
'mkdir -p .cache',
|
|
15
|
+
'mv `npm pack` .cache/',
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: '发布到远程服务器',
|
|
20
|
+
async run() {
|
|
21
|
+
exec(true, 'ls -al .cache')
|
|
22
|
+
const ssh = remote('gavin@192.168.5.121')
|
|
23
|
+
const dir = (path?: string) => join('/home/gavin/test', path ?? '')
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
await ssh.run('rm -f', dir('latest'))
|
|
27
|
+
await ssh.run('mkdir -p', dir(version))
|
|
28
|
+
await ssh.scp(`.cache/${file}`, dir())
|
|
29
|
+
await ssh.run('tar -zxvf', dir(file), '-C', dir(version))
|
|
30
|
+
await ssh.run('ln -s', dir(version), dir('latest'))
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
logError(e)
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// 执行流水线
|
|
41
|
+
PipeLine.run([deployTask])
|
package/bun.lock
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"workspaces": {
|
|
4
|
+
"": {
|
|
5
|
+
"name": "ts-cicd",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@types/bun": "latest",
|
|
8
|
+
"@types/node": "^20.12.7",
|
|
9
|
+
"vitest": "^1.6.0",
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"typescript": "^5",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
"packages": {
|
|
17
|
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
|
18
|
+
|
|
19
|
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
|
20
|
+
|
|
21
|
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
|
22
|
+
|
|
23
|
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
|
24
|
+
|
|
25
|
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
|
26
|
+
|
|
27
|
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
|
28
|
+
|
|
29
|
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
|
30
|
+
|
|
31
|
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
|
32
|
+
|
|
33
|
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
|
34
|
+
|
|
35
|
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
|
36
|
+
|
|
37
|
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
|
38
|
+
|
|
39
|
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
|
40
|
+
|
|
41
|
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
|
42
|
+
|
|
43
|
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
|
44
|
+
|
|
45
|
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
|
46
|
+
|
|
47
|
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
|
48
|
+
|
|
49
|
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
|
50
|
+
|
|
51
|
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
|
52
|
+
|
|
53
|
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
|
54
|
+
|
|
55
|
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
|
56
|
+
|
|
57
|
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
|
58
|
+
|
|
59
|
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
|
60
|
+
|
|
61
|
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
|
62
|
+
|
|
63
|
+
"@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
|
|
64
|
+
|
|
65
|
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
|
|
66
|
+
|
|
67
|
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.44.0", "", { "os": "android", "cpu": "arm" }, "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA=="],
|
|
68
|
+
|
|
69
|
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.44.0", "", { "os": "android", "cpu": "arm64" }, "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw=="],
|
|
70
|
+
|
|
71
|
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.44.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA=="],
|
|
72
|
+
|
|
73
|
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.44.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ=="],
|
|
74
|
+
|
|
75
|
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.44.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ=="],
|
|
76
|
+
|
|
77
|
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.44.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g=="],
|
|
78
|
+
|
|
79
|
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ=="],
|
|
80
|
+
|
|
81
|
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg=="],
|
|
82
|
+
|
|
83
|
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ=="],
|
|
84
|
+
|
|
85
|
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q=="],
|
|
86
|
+
|
|
87
|
+
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg=="],
|
|
88
|
+
|
|
89
|
+
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.44.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ=="],
|
|
90
|
+
|
|
91
|
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA=="],
|
|
92
|
+
|
|
93
|
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q=="],
|
|
94
|
+
|
|
95
|
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.44.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA=="],
|
|
96
|
+
|
|
97
|
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw=="],
|
|
98
|
+
|
|
99
|
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA=="],
|
|
100
|
+
|
|
101
|
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.44.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w=="],
|
|
102
|
+
|
|
103
|
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.44.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA=="],
|
|
104
|
+
|
|
105
|
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.44.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ=="],
|
|
106
|
+
|
|
107
|
+
"@sinclair/typebox": ["@sinclair/typebox@0.27.8", "", {}, "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="],
|
|
108
|
+
|
|
109
|
+
"@types/bun": ["@types/bun@1.2.17", "", { "dependencies": { "bun-types": "1.2.17" } }, "sha512-l/BYs/JYt+cXA/0+wUhulYJB6a6p//GTPiJ7nV+QHa8iiId4HZmnu/3J/SowP5g0rTiERY2kfGKXEK5Ehltx4Q=="],
|
|
110
|
+
|
|
111
|
+
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
|
112
|
+
|
|
113
|
+
"@types/node": ["@types/node@20.19.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA=="],
|
|
114
|
+
|
|
115
|
+
"@vitest/expect": ["@vitest/expect@1.6.1", "", { "dependencies": { "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "chai": "^4.3.10" } }, "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog=="],
|
|
116
|
+
|
|
117
|
+
"@vitest/runner": ["@vitest/runner@1.6.1", "", { "dependencies": { "@vitest/utils": "1.6.1", "p-limit": "^5.0.0", "pathe": "^1.1.1" } }, "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA=="],
|
|
118
|
+
|
|
119
|
+
"@vitest/snapshot": ["@vitest/snapshot@1.6.1", "", { "dependencies": { "magic-string": "^0.30.5", "pathe": "^1.1.1", "pretty-format": "^29.7.0" } }, "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ=="],
|
|
120
|
+
|
|
121
|
+
"@vitest/spy": ["@vitest/spy@1.6.1", "", { "dependencies": { "tinyspy": "^2.2.0" } }, "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw=="],
|
|
122
|
+
|
|
123
|
+
"@vitest/utils": ["@vitest/utils@1.6.1", "", { "dependencies": { "diff-sequences": "^29.6.3", "estree-walker": "^3.0.3", "loupe": "^2.3.7", "pretty-format": "^29.7.0" } }, "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g=="],
|
|
124
|
+
|
|
125
|
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
|
126
|
+
|
|
127
|
+
"acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
|
128
|
+
|
|
129
|
+
"ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
|
130
|
+
|
|
131
|
+
"assertion-error": ["assertion-error@1.1.0", "", {}, "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="],
|
|
132
|
+
|
|
133
|
+
"bun-types": ["bun-types@1.2.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ElC7ItwT3SCQwYZDYoAH+q6KT4Fxjl8DtZ6qDulUFBmXA8YB4xo+l54J9ZJN+k2pphfn9vk7kfubeSd5QfTVJQ=="],
|
|
134
|
+
|
|
135
|
+
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
|
136
|
+
|
|
137
|
+
"chai": ["chai@4.5.0", "", { "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.1.0" } }, "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw=="],
|
|
138
|
+
|
|
139
|
+
"check-error": ["check-error@1.0.3", "", { "dependencies": { "get-func-name": "^2.0.2" } }, "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg=="],
|
|
140
|
+
|
|
141
|
+
"confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
|
142
|
+
|
|
143
|
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
144
|
+
|
|
145
|
+
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
|
146
|
+
|
|
147
|
+
"deep-eql": ["deep-eql@4.1.4", "", { "dependencies": { "type-detect": "^4.0.0" } }, "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg=="],
|
|
148
|
+
|
|
149
|
+
"diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
|
|
150
|
+
|
|
151
|
+
"esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
|
|
152
|
+
|
|
153
|
+
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
|
154
|
+
|
|
155
|
+
"execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
|
156
|
+
|
|
157
|
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
158
|
+
|
|
159
|
+
"get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="],
|
|
160
|
+
|
|
161
|
+
"get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
|
162
|
+
|
|
163
|
+
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
|
164
|
+
|
|
165
|
+
"is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
|
166
|
+
|
|
167
|
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
168
|
+
|
|
169
|
+
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
|
170
|
+
|
|
171
|
+
"local-pkg": ["local-pkg@0.5.1", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.2.1" } }, "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ=="],
|
|
172
|
+
|
|
173
|
+
"loupe": ["loupe@2.3.7", "", { "dependencies": { "get-func-name": "^2.0.1" } }, "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA=="],
|
|
174
|
+
|
|
175
|
+
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
|
176
|
+
|
|
177
|
+
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
|
178
|
+
|
|
179
|
+
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
|
180
|
+
|
|
181
|
+
"mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="],
|
|
182
|
+
|
|
183
|
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
184
|
+
|
|
185
|
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
186
|
+
|
|
187
|
+
"npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
|
188
|
+
|
|
189
|
+
"onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
|
|
190
|
+
|
|
191
|
+
"p-limit": ["p-limit@5.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ=="],
|
|
192
|
+
|
|
193
|
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
194
|
+
|
|
195
|
+
"pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
|
|
196
|
+
|
|
197
|
+
"pathval": ["pathval@1.1.1", "", {}, "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="],
|
|
198
|
+
|
|
199
|
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
200
|
+
|
|
201
|
+
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
|
202
|
+
|
|
203
|
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
|
204
|
+
|
|
205
|
+
"pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
|
|
206
|
+
|
|
207
|
+
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
|
208
|
+
|
|
209
|
+
"rollup": ["rollup@4.44.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.44.0", "@rollup/rollup-android-arm64": "4.44.0", "@rollup/rollup-darwin-arm64": "4.44.0", "@rollup/rollup-darwin-x64": "4.44.0", "@rollup/rollup-freebsd-arm64": "4.44.0", "@rollup/rollup-freebsd-x64": "4.44.0", "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", "@rollup/rollup-linux-arm-musleabihf": "4.44.0", "@rollup/rollup-linux-arm64-gnu": "4.44.0", "@rollup/rollup-linux-arm64-musl": "4.44.0", "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-musl": "4.44.0", "@rollup/rollup-linux-s390x-gnu": "4.44.0", "@rollup/rollup-linux-x64-gnu": "4.44.0", "@rollup/rollup-linux-x64-musl": "4.44.0", "@rollup/rollup-win32-arm64-msvc": "4.44.0", "@rollup/rollup-win32-ia32-msvc": "4.44.0", "@rollup/rollup-win32-x64-msvc": "4.44.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA=="],
|
|
210
|
+
|
|
211
|
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
212
|
+
|
|
213
|
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
214
|
+
|
|
215
|
+
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
|
|
216
|
+
|
|
217
|
+
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
218
|
+
|
|
219
|
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
220
|
+
|
|
221
|
+
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
|
222
|
+
|
|
223
|
+
"std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="],
|
|
224
|
+
|
|
225
|
+
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
|
226
|
+
|
|
227
|
+
"strip-literal": ["strip-literal@2.1.1", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q=="],
|
|
228
|
+
|
|
229
|
+
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
|
230
|
+
|
|
231
|
+
"tinypool": ["tinypool@0.8.4", "", {}, "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ=="],
|
|
232
|
+
|
|
233
|
+
"tinyspy": ["tinyspy@2.2.1", "", {}, "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A=="],
|
|
234
|
+
|
|
235
|
+
"type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="],
|
|
236
|
+
|
|
237
|
+
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
|
238
|
+
|
|
239
|
+
"ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="],
|
|
240
|
+
|
|
241
|
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
242
|
+
|
|
243
|
+
"vite": ["vite@5.4.19", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA=="],
|
|
244
|
+
|
|
245
|
+
"vite-node": ["vite-node@1.6.1", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", "pathe": "^1.1.1", "picocolors": "^1.0.0", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA=="],
|
|
246
|
+
|
|
247
|
+
"vitest": ["vitest@1.6.1", "", { "dependencies": { "@vitest/expect": "1.6.1", "@vitest/runner": "1.6.1", "@vitest/snapshot": "1.6.1", "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", "execa": "^8.0.1", "local-pkg": "^0.5.0", "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", "std-env": "^3.5.0", "strip-literal": "^2.0.0", "tinybench": "^2.5.1", "tinypool": "^0.8.3", "vite": "^5.0.0", "vite-node": "1.6.1", "why-is-node-running": "^2.2.2" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "1.6.1", "@vitest/ui": "1.6.1", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag=="],
|
|
248
|
+
|
|
249
|
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
250
|
+
|
|
251
|
+
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
|
252
|
+
|
|
253
|
+
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
|
|
254
|
+
|
|
255
|
+
"bun-types/@types/node": ["@types/node@24.0.4", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA=="],
|
|
256
|
+
|
|
257
|
+
"mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
|
258
|
+
|
|
259
|
+
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
|
260
|
+
|
|
261
|
+
"pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
|
262
|
+
|
|
263
|
+
"bun-types/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
|
264
|
+
}
|
|
265
|
+
}
|
package/dev.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Airport任务调度系统开发文档
|
|
2
|
+
|
|
3
|
+
## 项目架构设计
|
|
4
|
+
|
|
5
|
+
Airport采用三级架构设计:Pipeline-Task-Step,形成清晰的层次结构,便于扩展和维护。
|
|
6
|
+
|
|
7
|
+
### 核心架构
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Airport
|
|
11
|
+
├── Pipeline: 管理多个Task的执行流程
|
|
12
|
+
│ ├── Task 1
|
|
13
|
+
│ │ ├── Step 1
|
|
14
|
+
│ │ ├── Step 2
|
|
15
|
+
│ │ └── ...
|
|
16
|
+
│ ├── Task 2
|
|
17
|
+
│ └── ...
|
|
18
|
+
├── Run: 异步处理本地命令
|
|
19
|
+
├── Exec: 同步处理本地命令
|
|
20
|
+
└── Remote: 处理远程服务器连接和操作
|
|
21
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "airport2",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "src/index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "vitest run",
|
|
8
|
+
"test:watch": "vitest",
|
|
9
|
+
"deploy": "bun airport.ts"
|
|
10
|
+
},
|
|
11
|
+
"prettier": {
|
|
12
|
+
"semi": false
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"typescript": "^5"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/bun": "latest",
|
|
19
|
+
"@types/node": "^20.12.7",
|
|
20
|
+
"vitest": "^1.6.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Step, exec } from '../index'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe('Airport任务调度系统', () => {
|
|
6
|
+
describe('Step', () => {
|
|
7
|
+
it('should execute shell command successfully', async () => {
|
|
8
|
+
const step = new Step({
|
|
9
|
+
name: 'Test Step',
|
|
10
|
+
run: 'echo hello',
|
|
11
|
+
})
|
|
12
|
+
const result = await step.execute()
|
|
13
|
+
expect(result).toBe(0)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
describe('Exec', () => {
|
|
18
|
+
it('test exec', async () => {
|
|
19
|
+
expect(exec('echo hello')).toBe('hello\n')
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Task } from './task'
|
|
2
|
+
import { log } from '../lib/log'
|
|
3
|
+
|
|
4
|
+
export class PipeLine {
|
|
5
|
+
public name?: string
|
|
6
|
+
private tasks: Task[]
|
|
7
|
+
|
|
8
|
+
static run(tasks: Task[]) {
|
|
9
|
+
return new PipeLine(tasks).run()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
constructor(tasks: Task[]) {
|
|
13
|
+
this.tasks = tasks
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 执行任务中的所有步骤
|
|
18
|
+
*/
|
|
19
|
+
async run() {
|
|
20
|
+
log('Start PipeLine: --------------------')
|
|
21
|
+
|
|
22
|
+
for (const task of this.tasks) {
|
|
23
|
+
await task.execute()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
log('----------- End PipeLine -----------')
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { run } from '../lib/run'
|
|
2
|
+
import type { StepRaw } from '../types'
|
|
3
|
+
|
|
4
|
+
export class Step {
|
|
5
|
+
public name: string
|
|
6
|
+
private test: boolean
|
|
7
|
+
private step: StepRaw
|
|
8
|
+
|
|
9
|
+
constructor(step: StepRaw, test: boolean = false) {
|
|
10
|
+
this.test = test
|
|
11
|
+
this.step = step
|
|
12
|
+
this.name = step.name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 执行步骤
|
|
17
|
+
*/
|
|
18
|
+
async execute(): Promise<any> {
|
|
19
|
+
if (typeof this.step.run === 'string') {
|
|
20
|
+
return this.runString()
|
|
21
|
+
} else if (Array.isArray(this.step.run)) {
|
|
22
|
+
return this.runArray()
|
|
23
|
+
} else {
|
|
24
|
+
// 函数类型的步骤
|
|
25
|
+
if (this.test) {
|
|
26
|
+
console.log(`[TEST MODE] Would execute function: ${this.step.run.name}`)
|
|
27
|
+
} else {
|
|
28
|
+
// 实际执行函数
|
|
29
|
+
return await this.step.run()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 处理字符串类型的命令执行
|
|
36
|
+
*/
|
|
37
|
+
private async runString() {
|
|
38
|
+
const runString = this.step.run as string
|
|
39
|
+
if (this.test) {
|
|
40
|
+
console.log(`[TEST MODE] Would execute: ${runString}`)
|
|
41
|
+
} else {
|
|
42
|
+
return await run(runString)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 处理字符串数组类型的命令执行
|
|
48
|
+
*/
|
|
49
|
+
private async runArray() {
|
|
50
|
+
const runArray = this.step.run as string[]
|
|
51
|
+
if (this.test) {
|
|
52
|
+
console.log(`[TEST MODE] Would execute array: ${runArray}`)
|
|
53
|
+
} else {
|
|
54
|
+
for (const cmd of runArray) {
|
|
55
|
+
await run(cmd)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Step } from './step'
|
|
2
|
+
import { log } from '../lib/log'
|
|
3
|
+
import type { TaskOptions, StepRaw } from '../types'
|
|
4
|
+
|
|
5
|
+
export class Task {
|
|
6
|
+
public name: string
|
|
7
|
+
public opt: TaskOptions
|
|
8
|
+
private steps: StepRaw[]
|
|
9
|
+
|
|
10
|
+
constructor(opt: TaskOptions) {
|
|
11
|
+
this.opt = opt
|
|
12
|
+
this.name = opt.name
|
|
13
|
+
this.steps = opt.steps
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 执行任务中的所有步骤
|
|
18
|
+
*/
|
|
19
|
+
async execute(test: boolean = false) {
|
|
20
|
+
const steps = this.steps.map((step) => new Step(step, test))
|
|
21
|
+
|
|
22
|
+
log(`Start Task:`, this.name)
|
|
23
|
+
|
|
24
|
+
for (const step of steps) {
|
|
25
|
+
log(`Start Task.Step:`, step.name)
|
|
26
|
+
|
|
27
|
+
await step.execute()
|
|
28
|
+
|
|
29
|
+
log(`End Task.Step:`, step.name)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
log(`End Task:`, this.name)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export * from './air/step'
|
|
2
|
+
export * from './air/task'
|
|
3
|
+
export * from './air/pipeline'
|
|
4
|
+
export * from './lib/run'
|
|
5
|
+
export * from './lib/remote'
|
|
6
|
+
export * from './lib/log'
|
|
7
|
+
|
|
8
|
+
// 导出默认的核心API
|
|
9
|
+
import { PipeLine } from './air/pipeline'
|
|
10
|
+
import { Task } from './air/task'
|
|
11
|
+
import { Step } from './air/step'
|
|
12
|
+
import { run } from './lib/run'
|
|
13
|
+
import { log, logError } from './lib/log'
|
|
14
|
+
import { remote } from './lib/remote'
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
PipeLine,
|
|
18
|
+
Task,
|
|
19
|
+
Step,
|
|
20
|
+
run,
|
|
21
|
+
remote,
|
|
22
|
+
log, logError,
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function isEmpty(obj: any) {
|
|
2
|
+
return [NaN, undefined, null, ''].includes(obj)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function formatTimestamp(timestamp: any = Date.now()) {
|
|
6
|
+
if (isEmpty(timestamp)) return ''
|
|
7
|
+
const date = new Date(timestamp)
|
|
8
|
+
const year = date.getFullYear()
|
|
9
|
+
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
10
|
+
const day = String(date.getDate()).padStart(2, '0')
|
|
11
|
+
const hours = String(date.getHours()).padStart(2, '0')
|
|
12
|
+
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|
13
|
+
const seconds = String(date.getSeconds()).padStart(2, '0')
|
|
14
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { run } from './run'
|
|
2
|
+
|
|
3
|
+
export interface RemoteConfig {
|
|
4
|
+
ssh: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function remote(ssh: string) {
|
|
8
|
+
return new Remote({ ssh })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class Remote {
|
|
12
|
+
constructor(private opt: RemoteConfig) {}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ssh远程执行命令
|
|
16
|
+
* @description 多个参数会自动`join`成一条命令:cmd.join(' ')
|
|
17
|
+
* @param cmd command to run
|
|
18
|
+
* @returns Promise<void>
|
|
19
|
+
*/
|
|
20
|
+
async run(...cmd: string[]): Promise<void> {
|
|
21
|
+
await run(`ssh ${this.opt.ssh} "${cmd.join(' ')}"`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async scp(src: string, dist: string) {
|
|
25
|
+
await run(`scp ${src} ${this.opt.ssh}:${dist}`)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { log } from './log'
|
|
2
|
+
import { spawn, execSync } from 'child_process'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 异步执行,控制台直接输出,`child_process.spawn`
|
|
6
|
+
* @param command Shell命令
|
|
7
|
+
* @returns Promise<any>
|
|
8
|
+
* @example await run('npm install')
|
|
9
|
+
* @example await run('npm run build')
|
|
10
|
+
*/
|
|
11
|
+
export const run = (command: string) =>
|
|
12
|
+
new Promise((resolve, reject) => {
|
|
13
|
+
log('Running:', command)
|
|
14
|
+
const child = spawn(command, {
|
|
15
|
+
shell: true,
|
|
16
|
+
stdio: 'inherit',
|
|
17
|
+
timeout: 30_000 // 30秒超时
|
|
18
|
+
})
|
|
19
|
+
child.on('exit', resolve)
|
|
20
|
+
child.on('error', reject)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 同步执行,`child_process.execSync`
|
|
25
|
+
* @param print 是否打印日志
|
|
26
|
+
* @param command Shell命令
|
|
27
|
+
* @returns Shell命令执行结果
|
|
28
|
+
* @example exec('ls -la')
|
|
29
|
+
* @example exec(true, 'ls -la')
|
|
30
|
+
*/
|
|
31
|
+
export function exec(command: string): string
|
|
32
|
+
export function exec(print: boolean, command: string): string
|
|
33
|
+
export function exec(print: boolean | string, command?: string): string {
|
|
34
|
+
if (typeof print === 'string') {
|
|
35
|
+
command = print
|
|
36
|
+
print = false
|
|
37
|
+
}
|
|
38
|
+
let output = execSync(command ?? 'echo').toString()
|
|
39
|
+
if (print) {
|
|
40
|
+
log('Running:', command)
|
|
41
|
+
log(output)
|
|
42
|
+
}
|
|
43
|
+
return output
|
|
44
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 步骤执行结果
|
|
3
|
+
*/
|
|
4
|
+
export interface StepResult {
|
|
5
|
+
success: boolean
|
|
6
|
+
output: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 步骤配置选项
|
|
11
|
+
*/
|
|
12
|
+
export interface StepRaw {
|
|
13
|
+
name: string
|
|
14
|
+
run: string | string[] | ((...args: any[]) => Promise<any>)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 任务执行结果
|
|
20
|
+
*/
|
|
21
|
+
export interface TaskResult {
|
|
22
|
+
success: boolean
|
|
23
|
+
stepResults: StepResult[]
|
|
24
|
+
name: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 任务配置选项
|
|
29
|
+
*/
|
|
30
|
+
export interface TaskOptions {
|
|
31
|
+
name: string
|
|
32
|
+
steps: StepRaw[]
|
|
33
|
+
test?: boolean
|
|
34
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './airport'
|