cobolx 1.0.0 → 1.0.2-canary.24
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/.github/workflows/ci.yml +165 -157
- package/Cargo.toml +1 -1
- package/bin/cobolx.js +81 -81
- package/package.json +27 -27
- package/scripts/install.js +145 -145
- package/scripts/prepare-version.js +44 -0
- package/src/ui/tui.rs +3 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -1,157 +1,165 @@
|
|
|
1
|
-
name: Rust CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ "main", "master", "release/**" ]
|
|
6
|
-
tags: [ "v*" ]
|
|
7
|
-
pull_request:
|
|
8
|
-
branches: [ "main", "master", "release/**" ]
|
|
9
|
-
|
|
10
|
-
env:
|
|
11
|
-
CARGO_TERM_COLOR: always
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
fmt:
|
|
15
|
-
name: Rustfmt Check
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
steps:
|
|
18
|
-
- name: Checkout Source Code
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: Install Stable Toolchain
|
|
22
|
-
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
23
|
-
with:
|
|
24
|
-
components: rustfmt
|
|
25
|
-
|
|
26
|
-
- name: Enforce Code Formatting
|
|
27
|
-
run: cargo fmt --all --check
|
|
28
|
-
|
|
29
|
-
clippy:
|
|
30
|
-
name: Clippy Lints Check
|
|
31
|
-
runs-on: ubuntu-latest
|
|
32
|
-
steps:
|
|
33
|
-
- name: Checkout Source Code
|
|
34
|
-
uses: actions/checkout@v4
|
|
35
|
-
|
|
36
|
-
- name: Install Stable Toolchain
|
|
37
|
-
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
38
|
-
with:
|
|
39
|
-
components: clippy
|
|
40
|
-
|
|
41
|
-
- name: Enforce Clippy warnings
|
|
42
|
-
run: cargo clippy --all-targets --all-features -- -D warnings
|
|
43
|
-
|
|
44
|
-
test:
|
|
45
|
-
name: Run Tests Suite
|
|
46
|
-
runs-on: ubuntu-latest
|
|
47
|
-
steps:
|
|
48
|
-
- name: Checkout Source Code
|
|
49
|
-
uses: actions/checkout@v4
|
|
50
|
-
|
|
51
|
-
- name: Install Stable Toolchain
|
|
52
|
-
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
53
|
-
|
|
54
|
-
- name: Run cargo test
|
|
55
|
-
run: cargo test --all-targets --all-features
|
|
56
|
-
|
|
57
|
-
audit:
|
|
58
|
-
name: Security Vulnerability Scan
|
|
59
|
-
runs-on: ubuntu-latest
|
|
60
|
-
steps:
|
|
61
|
-
- name: Checkout Source Code
|
|
62
|
-
uses: actions/checkout@v4
|
|
63
|
-
|
|
64
|
-
- name: Scan Vulnerable Dependencies
|
|
65
|
-
uses: actions-rust-lang/audit@v1
|
|
66
|
-
|
|
67
|
-
create-release:
|
|
68
|
-
name: Create GitHub Release
|
|
69
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
70
|
-
runs-on: ubuntu-latest
|
|
71
|
-
needs: [fmt, clippy, test, audit]
|
|
72
|
-
permissions:
|
|
73
|
-
contents: write
|
|
74
|
-
steps:
|
|
75
|
-
- name: Checkout Source Code
|
|
76
|
-
uses: actions/checkout@v4
|
|
77
|
-
|
|
78
|
-
- name:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- target: x86_64-
|
|
113
|
-
os:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
1
|
+
name: Rust CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main", "master", "release/**" ]
|
|
6
|
+
tags: [ "v*" ]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ "main", "master", "release/**" ]
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
CARGO_TERM_COLOR: always
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
fmt:
|
|
15
|
+
name: Rustfmt Check
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout Source Code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Install Stable Toolchain
|
|
22
|
+
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
23
|
+
with:
|
|
24
|
+
components: rustfmt
|
|
25
|
+
|
|
26
|
+
- name: Enforce Code Formatting
|
|
27
|
+
run: cargo fmt --all --check
|
|
28
|
+
|
|
29
|
+
clippy:
|
|
30
|
+
name: Clippy Lints Check
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout Source Code
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Install Stable Toolchain
|
|
37
|
+
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
38
|
+
with:
|
|
39
|
+
components: clippy
|
|
40
|
+
|
|
41
|
+
- name: Enforce Clippy warnings
|
|
42
|
+
run: cargo clippy --all-targets --all-features -- -D warnings
|
|
43
|
+
|
|
44
|
+
test:
|
|
45
|
+
name: Run Tests Suite
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- name: Checkout Source Code
|
|
49
|
+
uses: actions/checkout@v4
|
|
50
|
+
|
|
51
|
+
- name: Install Stable Toolchain
|
|
52
|
+
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
53
|
+
|
|
54
|
+
- name: Run cargo test
|
|
55
|
+
run: cargo test --all-targets --all-features
|
|
56
|
+
|
|
57
|
+
audit:
|
|
58
|
+
name: Security Vulnerability Scan
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- name: Checkout Source Code
|
|
62
|
+
uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- name: Scan Vulnerable Dependencies
|
|
65
|
+
uses: actions-rust-lang/audit@v1
|
|
66
|
+
|
|
67
|
+
create-release:
|
|
68
|
+
name: Create GitHub Release
|
|
69
|
+
if: startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/release/')
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
needs: [fmt, clippy, test, audit]
|
|
72
|
+
permissions:
|
|
73
|
+
contents: write
|
|
74
|
+
steps:
|
|
75
|
+
- name: Checkout Source Code
|
|
76
|
+
uses: actions/checkout@v4
|
|
77
|
+
|
|
78
|
+
- name: Prepare Dynamic Version
|
|
79
|
+
run: node scripts/prepare-version.js
|
|
80
|
+
|
|
81
|
+
- name: Create Release
|
|
82
|
+
uses: softprops/action-gh-release@v2
|
|
83
|
+
with:
|
|
84
|
+
tag_name: v${{ env.RELEASE_VERSION }}
|
|
85
|
+
name: v${{ env.RELEASE_VERSION }}
|
|
86
|
+
draft: false
|
|
87
|
+
prerelease: ${{ env.IS_CANARY == 'true' }}
|
|
88
|
+
generate_release_notes: true
|
|
89
|
+
|
|
90
|
+
build-binaries:
|
|
91
|
+
name: Build & Release Binaries
|
|
92
|
+
runs-on: ${{ matrix.os }}
|
|
93
|
+
needs: [fmt, clippy, test, audit, create-release]
|
|
94
|
+
if: |
|
|
95
|
+
always() &&
|
|
96
|
+
needs.fmt.result == 'success' &&
|
|
97
|
+
needs.clippy.result == 'success' &&
|
|
98
|
+
needs.test.result == 'success' &&
|
|
99
|
+
needs.audit.result == 'success' &&
|
|
100
|
+
needs.create-release.result == 'success'
|
|
101
|
+
permissions:
|
|
102
|
+
contents: write
|
|
103
|
+
strategy:
|
|
104
|
+
fail-fast: false
|
|
105
|
+
matrix:
|
|
106
|
+
include:
|
|
107
|
+
- target: x86_64-unknown-linux-gnu
|
|
108
|
+
os: ubuntu-latest
|
|
109
|
+
- target: aarch64-unknown-linux-gnu
|
|
110
|
+
os: ubuntu-latest
|
|
111
|
+
use-cross: true
|
|
112
|
+
- target: x86_64-apple-darwin
|
|
113
|
+
os: macos-latest
|
|
114
|
+
- target: aarch64-apple-darwin
|
|
115
|
+
os: macos-latest
|
|
116
|
+
- target: x86_64-pc-windows-msvc
|
|
117
|
+
os: windows-latest
|
|
118
|
+
steps:
|
|
119
|
+
- name: Checkout Source Code
|
|
120
|
+
uses: actions/checkout@v4
|
|
121
|
+
|
|
122
|
+
- name: Prepare Dynamic Version
|
|
123
|
+
run: node scripts/prepare-version.js
|
|
124
|
+
|
|
125
|
+
- name: Install Stable Toolchain
|
|
126
|
+
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
127
|
+
with:
|
|
128
|
+
target: ${{ matrix.target }}
|
|
129
|
+
|
|
130
|
+
- name: Build and Package Binary
|
|
131
|
+
uses: taiki-e/upload-rust-binary-action@v1
|
|
132
|
+
with:
|
|
133
|
+
bin: rdo
|
|
134
|
+
target: ${{ matrix.target }}
|
|
135
|
+
archive: $bin-$target
|
|
136
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
137
|
+
use-cross: ${{ matrix.use-cross || false }}
|
|
138
|
+
ref: refs/tags/v${{ env.RELEASE_VERSION }}
|
|
139
|
+
|
|
140
|
+
publish-npm:
|
|
141
|
+
name: Publish to npm
|
|
142
|
+
if: startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/release/')
|
|
143
|
+
runs-on: ubuntu-latest
|
|
144
|
+
needs: [build-binaries]
|
|
145
|
+
permissions:
|
|
146
|
+
id-token: write
|
|
147
|
+
contents: read
|
|
148
|
+
steps:
|
|
149
|
+
- name: Checkout Source Code
|
|
150
|
+
uses: actions/checkout@v4
|
|
151
|
+
|
|
152
|
+
- name: Prepare Dynamic Version
|
|
153
|
+
run: node scripts/prepare-version.js
|
|
154
|
+
|
|
155
|
+
- name: Set up Node.js
|
|
156
|
+
uses: actions/setup-node@v4
|
|
157
|
+
with:
|
|
158
|
+
node-version: '22'
|
|
159
|
+
registry-url: 'https://registry.npmjs.org'
|
|
160
|
+
|
|
161
|
+
- name: Upgrade npm CLI
|
|
162
|
+
run: npm install -g npm@latest
|
|
163
|
+
|
|
164
|
+
- name: Publish to npm
|
|
165
|
+
run: npm publish --tag ${{ env.NPM_TAG }} --access public --provenance
|
package/Cargo.toml
CHANGED
package/bin/cobolx.js
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { spawn } = require('child_process');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
|
|
7
|
-
const isWin = process.platform === 'win32';
|
|
8
|
-
const binName = isWin ? 'cobolx.exe' : 'cobolx';
|
|
9
|
-
const binaryPath = path.join(__dirname, binName);
|
|
10
|
-
|
|
11
|
-
if (!fs.existsSync(binaryPath)) {
|
|
12
|
-
console.error(`Error: Native binary not found at ${binaryPath}`);
|
|
13
|
-
console.error('Please try reinstalling the package: npm install -g cobolx');
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 1. Check for pending update notification from previous background checks
|
|
18
|
-
const noticeFile = path.join(__dirname, '.update-notice');
|
|
19
|
-
if (fs.existsSync(noticeFile)) {
|
|
20
|
-
try {
|
|
21
|
-
const notice = fs.readFileSync(noticeFile, 'utf8').trim();
|
|
22
|
-
if (notice) {
|
|
23
|
-
console.log('\n' + notice);
|
|
24
|
-
}
|
|
25
|
-
fs.unlinkSync(noticeFile);
|
|
26
|
-
} catch (err) {
|
|
27
|
-
// ignore
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 2. Start the native binary child process
|
|
32
|
-
const args = process.argv.slice(2);
|
|
33
|
-
const child = spawn(binaryPath, args, { stdio: 'inherit' });
|
|
34
|
-
|
|
35
|
-
child.on('error', (err) => {
|
|
36
|
-
console.error('Failed to start the native binary:', err);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
child.on('close', (code) => {
|
|
41
|
-
// 3. Trigger background update check
|
|
42
|
-
triggerBackgroundUpdateCheck();
|
|
43
|
-
process.exit(code ?? 0);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
function triggerBackgroundUpdateCheck() {
|
|
47
|
-
try {
|
|
48
|
-
const pkg = require('../package.json');
|
|
49
|
-
const cacheFile = path.join(__dirname, '.last-update-check');
|
|
50
|
-
const CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
|
|
51
|
-
const now = Date.now();
|
|
52
|
-
|
|
53
|
-
let lastCheck = 0;
|
|
54
|
-
if (fs.existsSync(cacheFile)) {
|
|
55
|
-
lastCheck = parseInt(fs.readFileSync(cacheFile, 'utf8'), 10) || 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (now - lastCheck < CHECK_INTERVAL) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Write new timestamp immediately to throttle requests
|
|
63
|
-
fs.writeFileSync(cacheFile, now.toString(), 'utf8');
|
|
64
|
-
|
|
65
|
-
// Spawn a detached background process to check for updates
|
|
66
|
-
const checkerScript = path.join(__dirname, 'check-update.js');
|
|
67
|
-
|
|
68
|
-
// Ignore outputs or pipe to a log file
|
|
69
|
-
const logFile = path.join(__dirname, '.checker-log');
|
|
70
|
-
const out = fs.openSync(logFile, 'a');
|
|
71
|
-
|
|
72
|
-
const child = spawn(process.execPath, [checkerScript], {
|
|
73
|
-
detached: true,
|
|
74
|
-
stdio: ['ignore', out, out]
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
child.unref();
|
|
78
|
-
} catch (err) {
|
|
79
|
-
// ignore
|
|
80
|
-
}
|
|
81
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
const isWin = process.platform === 'win32';
|
|
8
|
+
const binName = isWin ? 'cobolx.exe' : 'cobolx';
|
|
9
|
+
const binaryPath = path.join(__dirname, binName);
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(binaryPath)) {
|
|
12
|
+
console.error(`Error: Native binary not found at ${binaryPath}`);
|
|
13
|
+
console.error('Please try reinstalling the package: npm install -g cobolx');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 1. Check for pending update notification from previous background checks
|
|
18
|
+
const noticeFile = path.join(__dirname, '.update-notice');
|
|
19
|
+
if (fs.existsSync(noticeFile)) {
|
|
20
|
+
try {
|
|
21
|
+
const notice = fs.readFileSync(noticeFile, 'utf8').trim();
|
|
22
|
+
if (notice) {
|
|
23
|
+
console.log('\n' + notice);
|
|
24
|
+
}
|
|
25
|
+
fs.unlinkSync(noticeFile);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
// ignore
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2. Start the native binary child process
|
|
32
|
+
const args = process.argv.slice(2);
|
|
33
|
+
const child = spawn(binaryPath, args, { stdio: 'inherit' });
|
|
34
|
+
|
|
35
|
+
child.on('error', (err) => {
|
|
36
|
+
console.error('Failed to start the native binary:', err);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
child.on('close', (code) => {
|
|
41
|
+
// 3. Trigger background update check
|
|
42
|
+
triggerBackgroundUpdateCheck();
|
|
43
|
+
process.exit(code ?? 0);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function triggerBackgroundUpdateCheck() {
|
|
47
|
+
try {
|
|
48
|
+
const pkg = require('../package.json');
|
|
49
|
+
const cacheFile = path.join(__dirname, '.last-update-check');
|
|
50
|
+
const CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
|
|
53
|
+
let lastCheck = 0;
|
|
54
|
+
if (fs.existsSync(cacheFile)) {
|
|
55
|
+
lastCheck = parseInt(fs.readFileSync(cacheFile, 'utf8'), 10) || 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (now - lastCheck < CHECK_INTERVAL) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Write new timestamp immediately to throttle requests
|
|
63
|
+
fs.writeFileSync(cacheFile, now.toString(), 'utf8');
|
|
64
|
+
|
|
65
|
+
// Spawn a detached background process to check for updates
|
|
66
|
+
const checkerScript = path.join(__dirname, 'check-update.js');
|
|
67
|
+
|
|
68
|
+
// Ignore outputs or pipe to a log file
|
|
69
|
+
const logFile = path.join(__dirname, '.checker-log');
|
|
70
|
+
const out = fs.openSync(logFile, 'a');
|
|
71
|
+
|
|
72
|
+
const child = spawn(process.execPath, [checkerScript], {
|
|
73
|
+
detached: true,
|
|
74
|
+
stdio: ['ignore', out, out]
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
child.unref();
|
|
78
|
+
} catch (err) {
|
|
79
|
+
// ignore
|
|
80
|
+
}
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "cobolx",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CobolX CLI",
|
|
5
|
-
"main": "bin/cobolx.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"cobolx": "./bin/cobolx.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"postinstall": "node scripts/install.js"
|
|
11
|
-
},
|
|
12
|
-
"repository": {
|
|
13
|
-
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/WSPlXA/cobolX.git"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"cobol",
|
|
18
|
-
"rust",
|
|
19
|
-
"cli"
|
|
20
|
-
],
|
|
21
|
-
"author": "WSPlXA",
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"bugs": {
|
|
24
|
-
"url": "https://github.com/WSPlXA/cobolX/issues"
|
|
25
|
-
},
|
|
26
|
-
"homepage": "https://github.com/WSPlXA/cobolX#readme"
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "cobolx",
|
|
3
|
+
"version": "1.0.2-canary.24",
|
|
4
|
+
"description": "CobolX CLI",
|
|
5
|
+
"main": "bin/cobolx.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cobolx": "./bin/cobolx.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "node scripts/install.js"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/WSPlXA/cobolX.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"cobol",
|
|
18
|
+
"rust",
|
|
19
|
+
"cli"
|
|
20
|
+
],
|
|
21
|
+
"author": "WSPlXA",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/WSPlXA/cobolX/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/WSPlXA/cobolX#readme"
|
|
27
|
+
}
|
package/scripts/install.js
CHANGED
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const https = require('https');
|
|
4
|
-
const { execSync } = require('child_process');
|
|
5
|
-
|
|
6
|
-
const pkg = require('../package.json');
|
|
7
|
-
const version = pkg.version;
|
|
8
|
-
const repo = 'WSPlXA/cobolX';
|
|
9
|
-
const binDir = path.join(__dirname, '../bin');
|
|
10
|
-
|
|
11
|
-
// Map process.platform and process.arch to Rust target triples and archives
|
|
12
|
-
function getTarget() {
|
|
13
|
-
const platform = process.platform;
|
|
14
|
-
const arch = process.arch;
|
|
15
|
-
|
|
16
|
-
if (platform === 'win32' && arch === 'x64') {
|
|
17
|
-
return {
|
|
18
|
-
triple: 'x86_64-pc-windows-msvc',
|
|
19
|
-
ext: 'zip'
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
if (platform === 'darwin') {
|
|
23
|
-
if (arch === 'x64') {
|
|
24
|
-
return {
|
|
25
|
-
triple: 'x86_64-apple-darwin',
|
|
26
|
-
ext: 'tar.gz'
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
if (arch === 'arm64') {
|
|
30
|
-
return {
|
|
31
|
-
triple: 'aarch64-apple-darwin',
|
|
32
|
-
ext: 'tar.gz'
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (platform === 'linux') {
|
|
37
|
-
if (arch === 'x64') {
|
|
38
|
-
return {
|
|
39
|
-
triple: 'x86_64-unknown-linux-gnu',
|
|
40
|
-
ext: 'tar.gz'
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (arch === 'arm64') {
|
|
44
|
-
return {
|
|
45
|
-
triple: 'aarch64-unknown-linux-gnu',
|
|
46
|
-
ext: 'tar.gz'
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
throw new Error(`Unsupported platform/architecture: ${platform}/${arch}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function downloadFile(url, dest, callback) {
|
|
55
|
-
https.get(url, (res) => {
|
|
56
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
57
|
-
// Follow redirect
|
|
58
|
-
downloadFile(res.headers.location, dest, callback);
|
|
59
|
-
} else if (res.statusCode === 200) {
|
|
60
|
-
const file = fs.createWriteStream(dest);
|
|
61
|
-
res.pipe(file);
|
|
62
|
-
file.on('finish', () => {
|
|
63
|
-
file.close(callback);
|
|
64
|
-
});
|
|
65
|
-
} else {
|
|
66
|
-
callback(new Error(`Failed to download: HTTP ${res.statusCode} ${res.statusMessage}`));
|
|
67
|
-
}
|
|
68
|
-
}).on('error', (err) => {
|
|
69
|
-
callback(err);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function install() {
|
|
74
|
-
try {
|
|
75
|
-
const target = getTarget();
|
|
76
|
-
const archiveName = `rdo-${target.triple}.${target.ext}`;
|
|
77
|
-
const downloadUrl = `https://github.com/${repo}/releases/download/v${version}/${archiveName}`;
|
|
78
|
-
const tempFile = path.join(binDir, `temp-${archiveName}`);
|
|
79
|
-
|
|
80
|
-
console.log(`Downloading CobolX binary for ${target.triple}...`);
|
|
81
|
-
|
|
82
|
-
// Ensure bin directory exists
|
|
83
|
-
if (!fs.existsSync(binDir)) {
|
|
84
|
-
fs.mkdirSync(binDir, { recursive: true });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
downloadFile(downloadUrl, tempFile, (err) => {
|
|
88
|
-
if (err) {
|
|
89
|
-
console.error('Error downloading binary:', err.message);
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
console.log('Extracting binary...');
|
|
94
|
-
try {
|
|
95
|
-
if (target.ext === 'zip') {
|
|
96
|
-
// Decompress zip on Windows using PowerShell
|
|
97
|
-
const cmd = `powershell -Command "Expand-Archive -Path '${tempFile}' -DestinationPath '${binDir}' -Force"`;
|
|
98
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
99
|
-
} else {
|
|
100
|
-
// Decompress tar.gz on Unix
|
|
101
|
-
const cmd = `tar -xzf "${tempFile}" -C "${binDir}"`;
|
|
102
|
-
execSync(cmd, { stdio: 'inherit' });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Clean up temp archive
|
|
106
|
-
fs.unlinkSync(tempFile);
|
|
107
|
-
|
|
108
|
-
// Rename the binary from 'rdo' to 'cobolx'
|
|
109
|
-
const rawBinName = target.ext === 'zip' ? 'rdo.exe' : 'rdo';
|
|
110
|
-
const finalBinName = target.ext === 'zip' ? 'cobolx.exe' : 'cobolx';
|
|
111
|
-
|
|
112
|
-
const rawBinPath = path.join(binDir, rawBinName);
|
|
113
|
-
const finalBinPath = path.join(binDir, finalBinName);
|
|
114
|
-
|
|
115
|
-
if (fs.existsSync(rawBinPath)) {
|
|
116
|
-
fs.renameSync(rawBinPath, finalBinPath);
|
|
117
|
-
} else {
|
|
118
|
-
// Check if it was already named correctly or packaged differently
|
|
119
|
-
if (!fs.existsSync(finalBinPath)) {
|
|
120
|
-
throw new Error(`Could not find extracted binary in ${binDir}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Set execution permissions on Unix
|
|
125
|
-
if (target.ext !== 'zip') {
|
|
126
|
-
fs.chmodSync(finalBinPath, 0o755);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
console.log('CobolX binary installed successfully.');
|
|
130
|
-
} catch (extractErr) {
|
|
131
|
-
console.error('Error extracting binary:', extractErr.message);
|
|
132
|
-
// Clean up temp file in case of failure
|
|
133
|
-
if (fs.existsSync(tempFile)) {
|
|
134
|
-
fs.unlinkSync(tempFile);
|
|
135
|
-
}
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
} catch (err) {
|
|
140
|
-
console.error('Installation failed:', err.message);
|
|
141
|
-
process.exit(1);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
install();
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
const pkg = require('../package.json');
|
|
7
|
+
const version = pkg.version;
|
|
8
|
+
const repo = 'WSPlXA/cobolX';
|
|
9
|
+
const binDir = path.join(__dirname, '../bin');
|
|
10
|
+
|
|
11
|
+
// Map process.platform and process.arch to Rust target triples and archives
|
|
12
|
+
function getTarget() {
|
|
13
|
+
const platform = process.platform;
|
|
14
|
+
const arch = process.arch;
|
|
15
|
+
|
|
16
|
+
if (platform === 'win32' && arch === 'x64') {
|
|
17
|
+
return {
|
|
18
|
+
triple: 'x86_64-pc-windows-msvc',
|
|
19
|
+
ext: 'zip'
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (platform === 'darwin') {
|
|
23
|
+
if (arch === 'x64') {
|
|
24
|
+
return {
|
|
25
|
+
triple: 'x86_64-apple-darwin',
|
|
26
|
+
ext: 'tar.gz'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (arch === 'arm64') {
|
|
30
|
+
return {
|
|
31
|
+
triple: 'aarch64-apple-darwin',
|
|
32
|
+
ext: 'tar.gz'
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (platform === 'linux') {
|
|
37
|
+
if (arch === 'x64') {
|
|
38
|
+
return {
|
|
39
|
+
triple: 'x86_64-unknown-linux-gnu',
|
|
40
|
+
ext: 'tar.gz'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (arch === 'arm64') {
|
|
44
|
+
return {
|
|
45
|
+
triple: 'aarch64-unknown-linux-gnu',
|
|
46
|
+
ext: 'tar.gz'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
throw new Error(`Unsupported platform/architecture: ${platform}/${arch}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function downloadFile(url, dest, callback) {
|
|
55
|
+
https.get(url, (res) => {
|
|
56
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
57
|
+
// Follow redirect
|
|
58
|
+
downloadFile(res.headers.location, dest, callback);
|
|
59
|
+
} else if (res.statusCode === 200) {
|
|
60
|
+
const file = fs.createWriteStream(dest);
|
|
61
|
+
res.pipe(file);
|
|
62
|
+
file.on('finish', () => {
|
|
63
|
+
file.close(callback);
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
callback(new Error(`Failed to download: HTTP ${res.statusCode} ${res.statusMessage}`));
|
|
67
|
+
}
|
|
68
|
+
}).on('error', (err) => {
|
|
69
|
+
callback(err);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function install() {
|
|
74
|
+
try {
|
|
75
|
+
const target = getTarget();
|
|
76
|
+
const archiveName = `rdo-${target.triple}.${target.ext}`;
|
|
77
|
+
const downloadUrl = `https://github.com/${repo}/releases/download/v${version}/${archiveName}`;
|
|
78
|
+
const tempFile = path.join(binDir, `temp-${archiveName}`);
|
|
79
|
+
|
|
80
|
+
console.log(`Downloading CobolX binary for ${target.triple}...`);
|
|
81
|
+
|
|
82
|
+
// Ensure bin directory exists
|
|
83
|
+
if (!fs.existsSync(binDir)) {
|
|
84
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
downloadFile(downloadUrl, tempFile, (err) => {
|
|
88
|
+
if (err) {
|
|
89
|
+
console.error('Error downloading binary:', err.message);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('Extracting binary...');
|
|
94
|
+
try {
|
|
95
|
+
if (target.ext === 'zip') {
|
|
96
|
+
// Decompress zip on Windows using PowerShell
|
|
97
|
+
const cmd = `powershell -Command "Expand-Archive -Path '${tempFile}' -DestinationPath '${binDir}' -Force"`;
|
|
98
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
99
|
+
} else {
|
|
100
|
+
// Decompress tar.gz on Unix
|
|
101
|
+
const cmd = `tar -xzf "${tempFile}" -C "${binDir}"`;
|
|
102
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Clean up temp archive
|
|
106
|
+
fs.unlinkSync(tempFile);
|
|
107
|
+
|
|
108
|
+
// Rename the binary from 'rdo' to 'cobolx'
|
|
109
|
+
const rawBinName = target.ext === 'zip' ? 'rdo.exe' : 'rdo';
|
|
110
|
+
const finalBinName = target.ext === 'zip' ? 'cobolx.exe' : 'cobolx';
|
|
111
|
+
|
|
112
|
+
const rawBinPath = path.join(binDir, rawBinName);
|
|
113
|
+
const finalBinPath = path.join(binDir, finalBinName);
|
|
114
|
+
|
|
115
|
+
if (fs.existsSync(rawBinPath)) {
|
|
116
|
+
fs.renameSync(rawBinPath, finalBinPath);
|
|
117
|
+
} else {
|
|
118
|
+
// Check if it was already named correctly or packaged differently
|
|
119
|
+
if (!fs.existsSync(finalBinPath)) {
|
|
120
|
+
throw new Error(`Could not find extracted binary in ${binDir}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Set execution permissions on Unix
|
|
125
|
+
if (target.ext !== 'zip') {
|
|
126
|
+
fs.chmodSync(finalBinPath, 0o755);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('CobolX binary installed successfully.');
|
|
130
|
+
} catch (extractErr) {
|
|
131
|
+
console.error('Error extracting binary:', extractErr.message);
|
|
132
|
+
// Clean up temp file in case of failure
|
|
133
|
+
if (fs.existsSync(tempFile)) {
|
|
134
|
+
fs.unlinkSync(tempFile);
|
|
135
|
+
}
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
} catch (err) {
|
|
140
|
+
console.error('Installation failed:', err.message);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
install();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const githubRef = process.env.GITHUB_REF || '';
|
|
5
|
+
const runNumber = process.env.GITHUB_RUN_NUMBER || '0';
|
|
6
|
+
const runAttempt = process.env.GITHUB_RUN_ATTEMPT || '1';
|
|
7
|
+
const githubEnv = process.env.GITHUB_ENV;
|
|
8
|
+
|
|
9
|
+
const pkgPath = path.join(__dirname, '../package.json');
|
|
10
|
+
const cargoPath = path.join(__dirname, '../Cargo.toml');
|
|
11
|
+
|
|
12
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
13
|
+
const baseVersion = pkg.version;
|
|
14
|
+
|
|
15
|
+
let version = baseVersion;
|
|
16
|
+
let isCanary = 'false';
|
|
17
|
+
let npmTag = 'latest';
|
|
18
|
+
|
|
19
|
+
if (githubRef.startsWith('refs/tags/v')) {
|
|
20
|
+
version = githubRef.replace('refs/tags/v', '');
|
|
21
|
+
} else {
|
|
22
|
+
const attemptSuffix = runAttempt !== '1' ? `.${runAttempt}` : '';
|
|
23
|
+
version = `${baseVersion}-canary.${runNumber}${attemptSuffix}`;
|
|
24
|
+
isCanary = 'true';
|
|
25
|
+
npmTag = 'canary';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log(`Setting version to: ${version}`);
|
|
29
|
+
console.log(`Is Canary: ${isCanary}`);
|
|
30
|
+
console.log(`NPM Tag: ${npmTag}`);
|
|
31
|
+
|
|
32
|
+
// Update package.json
|
|
33
|
+
pkg.version = version;
|
|
34
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
35
|
+
|
|
36
|
+
// Update Cargo.toml
|
|
37
|
+
let cargo = fs.readFileSync(cargoPath, 'utf8');
|
|
38
|
+
cargo = cargo.replace(/version\s*=\s*"[^"]+"/, `version = "${version}"`);
|
|
39
|
+
fs.writeFileSync(cargoPath, cargo, 'utf8');
|
|
40
|
+
|
|
41
|
+
// Write to GITHUB_ENV
|
|
42
|
+
if (githubEnv && fs.existsSync(githubEnv)) {
|
|
43
|
+
fs.appendFileSync(githubEnv, `RELEASE_VERSION=${version}\nIS_CANARY=${isCanary}\nNPM_TAG=${npmTag}\n`, 'utf8');
|
|
44
|
+
}
|
package/src/ui/tui.rs
CHANGED
|
@@ -600,6 +600,9 @@ pub fn run_tui() -> Result<(), io::Error> {
|
|
|
600
600
|
// Non-blocking poll for crossterm events
|
|
601
601
|
if event::poll(std::time::Duration::from_millis(50))? {
|
|
602
602
|
if let Event::Key(key) = event::read()? {
|
|
603
|
+
if key.kind != event::KeyEventKind::Press {
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
603
606
|
if key.code == KeyCode::Char('c')
|
|
604
607
|
&& key.modifiers.contains(event::KeyModifiers::CONTROL)
|
|
605
608
|
{
|