@bobfrankston/msger 0.1.22 โ 0.1.23
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/index.d.ts +1 -0
- package/index.js +22 -3
- package/index.js.map +1 -1
- package/index.ts +139 -118
- package/msger-native/build-arm64.ts +92 -0
- package/msger-native/build-pi.ts +101 -0
- package/package.json +3 -1
- package/postinstall.js +5 -3
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -10,8 +10,18 @@ import fs from 'fs';
|
|
|
10
10
|
export async function showMessageBox(options) {
|
|
11
11
|
return new Promise((resolve, reject) => {
|
|
12
12
|
const isWindows = platform() === 'win32';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const arch = process.arch;
|
|
14
|
+
// Determine the binary name based on platform and architecture
|
|
15
|
+
let binaryName;
|
|
16
|
+
if (isWindows) {
|
|
17
|
+
binaryName = 'msgernative.exe';
|
|
18
|
+
}
|
|
19
|
+
else if (arch === 'arm64') {
|
|
20
|
+
binaryName = 'msgernative-arm64';
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
binaryName = 'msgernative';
|
|
24
|
+
}
|
|
15
25
|
const binaryPath = path.join(import.meta.dirname, 'msger-native', 'bin', binaryName);
|
|
16
26
|
// Check if binary exists
|
|
17
27
|
if (!fs.existsSync(binaryPath)) {
|
|
@@ -31,8 +41,13 @@ export async function showMessageBox(options) {
|
|
|
31
41
|
}
|
|
32
42
|
// Spawn the Rust binary
|
|
33
43
|
const child = spawn(binaryPath, [], {
|
|
34
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
44
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
+
detached: options.detach || false
|
|
35
46
|
});
|
|
47
|
+
// If detached, unref the child so parent can exit
|
|
48
|
+
if (options.detach) {
|
|
49
|
+
child.unref();
|
|
50
|
+
}
|
|
36
51
|
let stdout = '';
|
|
37
52
|
let stderr = '';
|
|
38
53
|
// Collect stdout
|
|
@@ -70,6 +85,10 @@ export async function showMessageBox(options) {
|
|
|
70
85
|
try {
|
|
71
86
|
child.stdin.write(JSON.stringify(options));
|
|
72
87
|
child.stdin.end();
|
|
88
|
+
// If detached, resolve immediately after sending options
|
|
89
|
+
if (options.detach) {
|
|
90
|
+
resolve({ button: 'detached', dismissed: false });
|
|
91
|
+
}
|
|
73
92
|
}
|
|
74
93
|
catch (error) {
|
|
75
94
|
reject(new Error(`Failed to write to stdin: ${error.message}`));
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
package/index.ts
CHANGED
|
@@ -1,118 +1,139 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import { platform } from 'os';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
|
|
6
|
-
export interface MessageBoxOptions {
|
|
7
|
-
title?: string;
|
|
8
|
-
message: string;
|
|
9
|
-
html?: string;
|
|
10
|
-
url?: string;
|
|
11
|
-
width?: number;
|
|
12
|
-
height?: number;
|
|
13
|
-
buttons?: string[];
|
|
14
|
-
defaultValue?: string;
|
|
15
|
-
allowInput?: boolean;
|
|
16
|
-
timeout?: number;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
* @
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
}
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { platform } from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
|
|
6
|
+
export interface MessageBoxOptions {
|
|
7
|
+
title?: string;
|
|
8
|
+
message: string;
|
|
9
|
+
html?: string;
|
|
10
|
+
url?: string;
|
|
11
|
+
width?: number;
|
|
12
|
+
height?: number;
|
|
13
|
+
buttons?: string[];
|
|
14
|
+
defaultValue?: string;
|
|
15
|
+
allowInput?: boolean;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
detach?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface MessageBoxResult {
|
|
21
|
+
button: string;
|
|
22
|
+
value?: string;
|
|
23
|
+
form?: Record<string, any>;
|
|
24
|
+
closed?: boolean;
|
|
25
|
+
dismissed?: boolean;
|
|
26
|
+
timeout?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Show a message box dialog using native Rust implementation
|
|
31
|
+
* @param options Message box configuration
|
|
32
|
+
* @returns Promise that resolves with user's response
|
|
33
|
+
*/
|
|
34
|
+
export async function showMessageBox(options: MessageBoxOptions): Promise<MessageBoxResult> {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const isWindows = platform() === 'win32';
|
|
37
|
+
const arch = process.arch;
|
|
38
|
+
|
|
39
|
+
// Determine the binary name based on platform and architecture
|
|
40
|
+
let binaryName: string;
|
|
41
|
+
if (isWindows) {
|
|
42
|
+
binaryName = 'msgernative.exe';
|
|
43
|
+
} else if (arch === 'arm64') {
|
|
44
|
+
binaryName = 'msgernative-arm64';
|
|
45
|
+
} else {
|
|
46
|
+
binaryName = 'msgernative';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const binaryPath = path.join(import.meta.dirname, 'msger-native', 'bin', binaryName);
|
|
50
|
+
|
|
51
|
+
// Check if binary exists
|
|
52
|
+
if (!fs.existsSync(binaryPath)) {
|
|
53
|
+
reject(new Error(`Binary not found: ${binaryPath}`));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// On Unix systems, check if binary is executable
|
|
58
|
+
if (!isWindows) {
|
|
59
|
+
try {
|
|
60
|
+
fs.accessSync(binaryPath, fs.constants.X_OK);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
reject(new Error(
|
|
63
|
+
`Binary is not executable: ${binaryPath}\n` +
|
|
64
|
+
`Please run: sudo chmod +x ${binaryPath}`
|
|
65
|
+
));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Spawn the Rust binary
|
|
71
|
+
const child = spawn(binaryPath, [], {
|
|
72
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
73
|
+
detached: options.detach || false
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// If detached, unref the child so parent can exit
|
|
77
|
+
if (options.detach) {
|
|
78
|
+
child.unref();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let stdout = '';
|
|
82
|
+
let stderr = '';
|
|
83
|
+
|
|
84
|
+
// Collect stdout
|
|
85
|
+
child.stdout.on('data', (data) => {
|
|
86
|
+
stdout += data.toString();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Collect stderr
|
|
90
|
+
child.stderr.on('data', (data) => {
|
|
91
|
+
stderr += data.toString();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Handle process completion
|
|
95
|
+
child.on('close', (code) => {
|
|
96
|
+
if (code !== 0) {
|
|
97
|
+
reject(new Error(`msger exited with code ${code}: ${stderr}`));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const result = JSON.parse(stdout.trim()) as MessageBoxResult;
|
|
103
|
+
resolve(result);
|
|
104
|
+
} catch (error: any) {
|
|
105
|
+
reject(new Error(`Failed to parse result: ${error.message}\nOutput: ${stdout}`));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Handle process errors
|
|
110
|
+
child.on('error', (error) => {
|
|
111
|
+
reject(new Error(`Failed to spawn msger: ${error.message}`));
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Handle stdin errors (e.g., EPIPE when child dies early)
|
|
115
|
+
child.stdin.on('error', (error: any) => {
|
|
116
|
+
// Don't reject here - the 'close' or 'error' event will handle it
|
|
117
|
+
// This prevents unhandled EPIPE errors
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Send options to stdin
|
|
121
|
+
try {
|
|
122
|
+
child.stdin.write(JSON.stringify(options));
|
|
123
|
+
child.stdin.end();
|
|
124
|
+
|
|
125
|
+
// If detached, resolve immediately after sending options
|
|
126
|
+
if (options.detach) {
|
|
127
|
+
resolve({ button: 'detached', dismissed: false });
|
|
128
|
+
}
|
|
129
|
+
} catch (error: any) {
|
|
130
|
+
reject(new Error(`Failed to write to stdin: ${error.message}`));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If run directly (not imported), invoke CLI
|
|
136
|
+
if (import.meta.main) {
|
|
137
|
+
const { default: cliMain } = await import('./cli.js');
|
|
138
|
+
await cliMain();
|
|
139
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
console.log('๐ฆพ Building ARM64 binary via WSL...');
|
|
11
|
+
|
|
12
|
+
// Get the WSL path
|
|
13
|
+
const windowsPath = __dirname.replace(/\\/g, '/');
|
|
14
|
+
const driveLetter = windowsPath.charAt(0).toLowerCase();
|
|
15
|
+
const pathWithoutDrive = windowsPath.substring(2);
|
|
16
|
+
const wslPath = `/mnt/${driveLetter}${pathWithoutDrive}`;
|
|
17
|
+
|
|
18
|
+
console.log(`๐ WSL path: ${wslPath}`);
|
|
19
|
+
|
|
20
|
+
// Check for Rust in WSL
|
|
21
|
+
console.log('๐ Checking for Rust/Cargo in WSL...');
|
|
22
|
+
try {
|
|
23
|
+
execSync('wsl bash -c "command -v cargo"', { stdio: 'pipe' });
|
|
24
|
+
console.log('โ
Rust/Cargo found');
|
|
25
|
+
} catch {
|
|
26
|
+
console.log('โ ๏ธ Rust/Cargo not found in WSL, installing...');
|
|
27
|
+
execSync('wsl bash -c "curl --proto \'=https\' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"', { stdio: 'inherit' });
|
|
28
|
+
console.log('โ
Rust installed successfully');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check for ARM64 target
|
|
32
|
+
console.log('๐ Checking for ARM64 cross-compilation target...');
|
|
33
|
+
try {
|
|
34
|
+
const targets = execSync('wsl bash -c ". $HOME/.cargo/env && rustup target list --installed"', { encoding: 'utf8' });
|
|
35
|
+
if (!targets.includes('aarch64-unknown-linux-gnu')) {
|
|
36
|
+
console.log('๐ฆ Adding ARM64 target...');
|
|
37
|
+
execSync('wsl bash -c ". $HOME/.cargo/env && rustup target add aarch64-unknown-linux-gnu"', { stdio: 'inherit' });
|
|
38
|
+
console.log('โ
ARM64 target added');
|
|
39
|
+
} else {
|
|
40
|
+
console.log('โ
ARM64 target already installed');
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.log('๐ฆ Adding ARM64 target...');
|
|
44
|
+
execSync('wsl bash -c ". $HOME/.cargo/env && rustup target add aarch64-unknown-linux-gnu"', { stdio: 'inherit' });
|
|
45
|
+
console.log('โ
ARM64 target added');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Check for ARM64 cross-compiler
|
|
49
|
+
console.log('๐ Checking for ARM64 cross-compiler...');
|
|
50
|
+
try {
|
|
51
|
+
execSync('wsl bash -c "command -v aarch64-linux-gnu-gcc"', { stdio: 'pipe' });
|
|
52
|
+
console.log('โ
ARM64 cross-compiler found');
|
|
53
|
+
} catch {
|
|
54
|
+
console.log('๐ฆ Installing ARM64 cross-compiler...');
|
|
55
|
+
execSync('wsl bash -c "sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu"', { stdio: 'inherit' });
|
|
56
|
+
console.log('โ
ARM64 cross-compiler installed');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check for build dependencies
|
|
60
|
+
console.log('๐ Checking for build dependencies in WSL...');
|
|
61
|
+
try {
|
|
62
|
+
execSync('wsl bash -c "pkg-config --exists gtk+-3.0 webkit2gtk-4.1"', { stdio: 'pipe' });
|
|
63
|
+
console.log('โ
Build dependencies found');
|
|
64
|
+
} catch {
|
|
65
|
+
console.log('โ ๏ธ Build dependencies not found, installing...');
|
|
66
|
+
execSync('wsl bash -c "sudo apt-get update && sudo apt-get install -y pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libsoup-3.0-dev"', { stdio: 'inherit' });
|
|
67
|
+
console.log('โ
Build dependencies installed');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Build for ARM64
|
|
71
|
+
console.log('\n๐ฆ Building ARM64 binary...');
|
|
72
|
+
const buildCmd = `wsl bash -c "cd ${wslPath} && . $HOME/.cargo/env && export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc && PKG_CONFIG_ALLOW_CROSS=1 cargo build --release --target aarch64-unknown-linux-gnu"`;
|
|
73
|
+
execSync(buildCmd, { stdio: 'inherit' });
|
|
74
|
+
console.log('โ
ARM64 build completed');
|
|
75
|
+
|
|
76
|
+
// Copy the binary
|
|
77
|
+
const sourcePath = path.join(__dirname, 'target', 'aarch64-unknown-linux-gnu', 'release', 'msgernative');
|
|
78
|
+
const destDir = path.join(__dirname, 'bin');
|
|
79
|
+
const destPath = path.join(destDir, 'msgernative-arm64');
|
|
80
|
+
|
|
81
|
+
if (!fs.existsSync(destDir)) {
|
|
82
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
86
|
+
console.log(`โ
Binary copied to: ${destPath}`);
|
|
87
|
+
|
|
88
|
+
const stats = fs.statSync(destPath);
|
|
89
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
90
|
+
console.log(`๐ Binary size: ${sizeMB} MB`);
|
|
91
|
+
|
|
92
|
+
console.log('\n๐ ARM64 build process completed!');
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
// Configuration - UPDATE THESE VALUES
|
|
7
|
+
const PI_HOST = 'pi4c'; // or 'pi@raspberrypi.local' or 'pi@192.168.1.xxx'
|
|
8
|
+
const PI_BUILD_DIR = '/tmp/msger-native-build';
|
|
9
|
+
|
|
10
|
+
console.log('๐ฆพ Building ARM64 binary via SSH to Raspberry Pi...');
|
|
11
|
+
console.log(`๐ Target: ${PI_HOST}`);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Test SSH connection
|
|
15
|
+
console.log('๐ Testing SSH connection...');
|
|
16
|
+
execSync(`ssh ${PI_HOST} "echo Connected"`, { stdio: 'pipe' });
|
|
17
|
+
console.log('โ
SSH connection successful');
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('โ Cannot connect to Pi via SSH');
|
|
20
|
+
console.error(' Make sure you can run: ssh ' + PI_HOST);
|
|
21
|
+
console.error(' You may need to set up SSH keys: ssh-copy-id ' + PI_HOST);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Create build directory on Pi
|
|
26
|
+
console.log('๐ Creating build directory on Pi...');
|
|
27
|
+
execSync(`ssh ${PI_HOST} "mkdir -p ${PI_BUILD_DIR}/src"`, { stdio: 'inherit' });
|
|
28
|
+
|
|
29
|
+
// Copy source files to Pi
|
|
30
|
+
console.log('๐ค Copying source files to Pi...');
|
|
31
|
+
execSync(`scp Cargo.toml ${PI_HOST}:${PI_BUILD_DIR}/`, { stdio: 'inherit', cwd: import.meta.dirname });
|
|
32
|
+
execSync(`scp -r src/* ${PI_HOST}:${PI_BUILD_DIR}/src/`, { stdio: 'inherit', cwd: import.meta.dirname });
|
|
33
|
+
|
|
34
|
+
// Check for Rust on Pi
|
|
35
|
+
console.log('๐ Checking for Rust/Cargo on Pi...');
|
|
36
|
+
try {
|
|
37
|
+
execSync(`ssh ${PI_HOST} "command -v cargo"`, { stdio: 'pipe' });
|
|
38
|
+
console.log('โ
Rust/Cargo found');
|
|
39
|
+
} catch {
|
|
40
|
+
console.log('๐ฆ Installing Rust on Pi...');
|
|
41
|
+
execSync(`ssh ${PI_HOST} "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"`, { stdio: 'inherit' });
|
|
42
|
+
console.log('โ
Rust installed successfully');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Ensure pkg-config is installed first (required to check for other dependencies)
|
|
46
|
+
console.log('๐ง Ensuring pkg-config is installed on Pi...');
|
|
47
|
+
try {
|
|
48
|
+
execSync(`ssh ${PI_HOST} "command -v pkg-config"`, { stdio: 'pipe' });
|
|
49
|
+
console.log('โ
pkg-config found');
|
|
50
|
+
} catch {
|
|
51
|
+
console.log('๐ฆ Installing pkg-config on Pi...');
|
|
52
|
+
execSync(`ssh ${PI_HOST} "sudo apt-get update && sudo apt-get install -y pkg-config"`, { stdio: 'inherit' });
|
|
53
|
+
console.log('โ
pkg-config installed');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check for build dependencies on Pi
|
|
57
|
+
console.log('๐ Checking for build dependencies on Pi...');
|
|
58
|
+
try {
|
|
59
|
+
execSync(`ssh ${PI_HOST} "pkg-config --exists gtk+-3.0 webkit2gtk-4.0"`, { stdio: 'pipe' });
|
|
60
|
+
console.log('โ
Build dependencies found');
|
|
61
|
+
} catch {
|
|
62
|
+
console.log('๐ฆ Installing build dependencies on Pi...');
|
|
63
|
+
execSync(`ssh ${PI_HOST} "sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libsoup2.4-dev"`, { stdio: 'inherit' });
|
|
64
|
+
console.log('โ
Build dependencies installed');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Build on Pi
|
|
68
|
+
console.log('\n๐ฆ Building ARM64 binary on Pi...');
|
|
69
|
+
try {
|
|
70
|
+
execSync(`ssh ${PI_HOST} "cd ${PI_BUILD_DIR} && export PATH=~/.cargo/bin:\\$PATH && export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig && cargo build --release"`, { stdio: 'inherit' });
|
|
71
|
+
console.log('โ
ARM64 build completed');
|
|
72
|
+
} catch (error: any) {
|
|
73
|
+
console.error('โ Build failed:');
|
|
74
|
+
console.error(error.stdout?.toString());
|
|
75
|
+
console.error(error.stderr?.toString());
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Copy binary back
|
|
80
|
+
console.log('๐ฅ Copying binary back from Pi...');
|
|
81
|
+
const destDir = path.join(import.meta.dirname, 'bin');
|
|
82
|
+
if (!fs.existsSync(destDir)) {
|
|
83
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const destPath = path.join(destDir, 'msgernative-arm64');
|
|
87
|
+
execSync(`scp ${PI_HOST}:${PI_BUILD_DIR}/target/release/msgernative ${destPath}`, { stdio: 'inherit' });
|
|
88
|
+
|
|
89
|
+
// Set execute permissions
|
|
90
|
+
fs.chmodSync(destPath, 0o755);
|
|
91
|
+
|
|
92
|
+
const stats = fs.statSync(destPath);
|
|
93
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
94
|
+
console.log(`โ
Binary copied to: ${destPath}`);
|
|
95
|
+
console.log(`๐ Binary size: ${sizeMB} MB`);
|
|
96
|
+
|
|
97
|
+
// Cleanup on Pi
|
|
98
|
+
console.log('๐งน Cleaning up on Pi...');
|
|
99
|
+
execSync(`ssh ${PI_HOST} "rm -rf ${PI_BUILD_DIR}"`, { stdio: 'inherit' });
|
|
100
|
+
|
|
101
|
+
console.log('\n๐ ARM64 build process completed!');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/msger",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"build": "npm run build:ts && npm run build:native",
|
|
18
18
|
"build:native": "cd msger-native && npm run build",
|
|
19
19
|
"build:native:wsl": "cd msger-native && npm run build:wsl",
|
|
20
|
+
"build:native:pi": "cd msger-native && npm run build:pi",
|
|
20
21
|
"build:native:all": "npm run build:native && npm run build:native:wsl",
|
|
22
|
+
"build:native:allpiignored": "npm run build:native:pi",
|
|
21
23
|
"build:ts": "tsc",
|
|
22
24
|
"watch": "tsc -w",
|
|
23
25
|
"clean": "rm -rf *.js *.d.ts *.js.map bin && cd msger-native && cargo clean",
|
package/postinstall.js
CHANGED
|
@@ -9,15 +9,17 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const isWindows = process.platform === 'win32';
|
|
10
10
|
|
|
11
11
|
if (!isWindows) {
|
|
12
|
-
const
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
const binaryName = arch === 'arm64' ? 'msgernative-arm64' : 'msgernative';
|
|
14
|
+
const binaryPath = path.join(__dirname, 'msger-native', 'bin', binaryName);
|
|
13
15
|
|
|
14
16
|
if (fs.existsSync(binaryPath)) {
|
|
15
17
|
try {
|
|
16
18
|
fs.chmodSync(binaryPath, 0o755);
|
|
17
|
-
console.log(
|
|
19
|
+
console.log(`โ
Set execute permissions on ${binaryName} binary`);
|
|
18
20
|
} catch (error) {
|
|
19
21
|
console.warn(`โ ๏ธ Could not set execute permission on ${binaryPath}: ${error.message}`);
|
|
20
|
-
console.warn(
|
|
22
|
+
console.warn(` You may need to run: sudo chmod +x ${binaryPath}`);
|
|
21
23
|
}
|
|
22
24
|
} else {
|
|
23
25
|
console.warn(`โ ๏ธ Binary not found at ${binaryPath}`);
|