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.
@@ -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: Create Release
79
- uses: softprops/action-gh-release@v2
80
- with:
81
- draft: false
82
- prerelease: false
83
- generate_release_notes: true
84
-
85
- build-binaries:
86
- name: Build & Release Binaries
87
- runs-on: ${{ matrix.os }}
88
- needs: [fmt, clippy, test, audit, create-release]
89
- if: |
90
- always() &&
91
- needs.fmt.result == 'success' &&
92
- needs.clippy.result == 'success' &&
93
- needs.test.result == 'success' &&
94
- needs.audit.result == 'success' &&
95
- (needs.create-release.result == 'success' || needs.create-release.result == 'skipped') &&
96
- (startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/'))
97
- permissions:
98
- contents: write
99
- strategy:
100
- fail-fast: false
101
- matrix:
102
- include:
103
- - target: x86_64-unknown-linux-gnu
104
- os: ubuntu-latest
105
- - target: aarch64-unknown-linux-gnu
106
- os: ubuntu-latest
107
- use-cross: true
108
- - target: x86_64-apple-darwin
109
- os: macos-latest
110
- - target: aarch64-apple-darwin
111
- os: macos-latest
112
- - target: x86_64-pc-windows-msvc
113
- os: windows-latest
114
- steps:
115
- - name: Checkout Source Code
116
- uses: actions/checkout@v4
117
-
118
- - name: Install Stable Toolchain
119
- uses: actions-rust-lang/setup-rust-toolchain@v1
120
- with:
121
- target: ${{ matrix.target }}
122
-
123
- - name: Build and Package Binary
124
- uses: taiki-e/upload-rust-binary-action@v1
125
- with:
126
- bin: rdo
127
- target: ${{ matrix.target }}
128
- archive: $bin-$target
129
- token: ${{ secrets.GITHUB_TOKEN }}
130
- use-cross: ${{ matrix.use-cross || false }}
131
- dry-run: ${{ !startsWith(github.ref, 'refs/tags/') }}
132
-
133
-
134
-
135
- publish-npm:
136
- name: Publish to npm
137
- if: startsWith(github.ref, 'refs/tags/')
138
- runs-on: ubuntu-latest
139
- needs: [build-binaries]
140
- permissions:
141
- id-token: write
142
- contents: read
143
- steps:
144
- - name: Checkout Source Code
145
- uses: actions/checkout@v4
146
-
147
- - name: Set up Node.js
148
- uses: actions/setup-node@v4
149
- with:
150
- node-version: '22'
151
- registry-url: 'https://registry.npmjs.org'
152
-
153
- - name: Upgrade npm CLI
154
- run: npm install -g npm@latest
155
-
156
- - name: Publish to npm
157
- run: npm publish --access public --provenance
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
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rdo"
3
- version = "0.1.0"
3
+ version = "1.0.2-canary.24"
4
4
  edition = "2024"
5
5
 
6
6
  [dependencies]
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.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
+ }
@@ -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
  {