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 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
@@ -0,0 +1,5 @@
1
+ {
2
+ "cSpell.words": [
3
+ "zxvf"
4
+ ]
5
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # CHANGELOG
2
+
3
+ ## [0.0.1] - 2025-06-25
4
+
5
+ ### 初始版本发布
6
+ - ✅ 实现Pipeline-Task-Step三级架构
7
+ - ✅ 支持本地命令执行和远程SSH操作
8
+ - ✅ 添加单元测试框架和示例测试
9
+ - ✅ 实现测试模式,支持命令预览
10
+ - ✅ 完成基础文档和开发计划
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,9 @@
1
+ import { formatTimestamp } from './date'
2
+
3
+ export const log = (...args: any[]) => {
4
+ console.log(`[${formatTimestamp()}]`, ...args)
5
+ }
6
+
7
+ export const logError = (...args: any[]) => {
8
+ console.error(`[${formatTimestamp()}]`, ...args)
9
+ }
@@ -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'