@bobfrankston/msger 0.1.128 → 0.1.130

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.
Files changed (48) hide show
  1. package/cruft/clean.d.ts +3 -0
  2. package/cruft/clean.d.ts.map +1 -0
  3. package/cruft/clean.js +71 -0
  4. package/cruft/clean.js.map +1 -0
  5. package/{msgernative-linux-x64 → cruft/msgernative-linux-x64} +0 -0
  6. package/docs/README.md +26 -0
  7. package/msger-native/bin/msgernative +0 -0
  8. package/msger-native/bin/msgernative-arm64 +0 -0
  9. package/msger-native/bin/msgernative.exe +0 -0
  10. package/msger-native/builder/README.md +69 -0
  11. package/msger-native/builder/build-config.json +14 -0
  12. package/msger-native/builder/build-under-wsl.ts +210 -0
  13. package/msger-native/builder/builder.ts +394 -0
  14. package/msger-native/builder/clean.ts +86 -0
  15. package/msger-native/builder/postinstall.ts +107 -0
  16. package/msger-native/package.json +1 -4
  17. package/msger-native/pibuild/README.md +42 -0
  18. package/msger-native/src/main.rs +5 -4
  19. package/package.json +5 -10
  20. /package/{msger-native → cruft}/apply-zoom-fix.js +0 -0
  21. /package/{msger-native → cruft}/build-arm64.ts +0 -0
  22. /package/{msger-native → cruft}/build-pi.ts +0 -0
  23. /package/{msger-native → cruft}/build-pi.ts.backup +0 -0
  24. /package/{msger-native → cruft}/build-pi.ts.old +0 -0
  25. /package/{msger-native → cruft}/build-wsl.ts +0 -0
  26. /package/{msger-native → cruft}/build.js +0 -0
  27. /package/{msger-native → cruft}/build.ts +0 -0
  28. /package/{msgernative-win32-x64.exe → cruft/msgernative-win32-x64.exe} +0 -0
  29. /package/{postinstall.js → cruft/postinstall.js} +0 -0
  30. /package/{test-size.d.ts → cruft/test-size.d.ts} +0 -0
  31. /package/{CHANGELOG.md → docs/CHANGELOG.md} +0 -0
  32. /package/{CLOSE-API.md → docs/CLOSE-API.md} +0 -0
  33. /package/{DEVELOPERS.md → docs/DEVELOPERS.md} +0 -0
  34. /package/{FULLSCREEN-FEATURE.md → docs/FULLSCREEN-FEATURE.md} +0 -0
  35. /package/{IMPLEMENTATION-SUMMARY.md → docs/IMPLEMENTATION-SUMMARY.md} +0 -0
  36. /package/{KNOWN-BUGS.md → docs/KNOWN-BUGS.md} +0 -0
  37. /package/{MSGER-API-SUMMARY.md → docs/MSGER-API-SUMMARY.md} +0 -0
  38. /package/{MSGER-API.md → docs/MSGER-API.md} +0 -0
  39. /package/{PI-RENDERING-NOTES.md → docs/PI-RENDERING-NOTES.md} +0 -0
  40. /package/{RELEASE-NOTES.md → docs/RELEASE-NOTES.md} +0 -0
  41. /package/{TODO.md → docs/TODO.md} +0 -0
  42. /package/{SESSION-2025-11-06.md → docs/sessions/SESSION-2025-11-06.md} +0 -0
  43. /package/{SESSION-NOTES.md → docs/sessions/SESSION-NOTES.md} +0 -0
  44. /package/{SESSION-RESUME-NOTES.md → docs/sessions/SESSION-RESUME-NOTES.md} +0 -0
  45. /package/msger-native/{build-on-pi.sh → pibuild/build-on-pi.sh} +0 -0
  46. /package/msger-native/{build-pi.ps1 → pibuild/build-pi.ps1} +0 -0
  47. /package/msger-native/{pi-diagnostics.ts → pibuild/pi-diagnostics.ts} +0 -0
  48. /package/msger-native/{setup-arm64-toolchain.sh → pibuild/setup-arm64-toolchain.sh} +0 -0
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["clean.js"],"names":[],"mappings":""}
package/cruft/clean.js ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Cross-platform clean script
4
+ * Removes build artifacts
5
+ */
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { execSync } from 'child_process';
9
+ const rootDir = process.cwd();
10
+ console.log('🧹 Cleaning build artifacts...\n');
11
+ // Files to delete in root directory
12
+ const rootPatterns = [
13
+ '*.js',
14
+ '*.d.ts',
15
+ '*.d.ts.map',
16
+ '*.js.map'
17
+ ];
18
+ // Directories to exclude
19
+ const excludeDirs = ['node_modules', '.git', 'msger-native'];
20
+ function deleteFile(filePath) {
21
+ try {
22
+ fs.unlinkSync(filePath);
23
+ return true;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ function matchesPattern(filename, pattern) {
30
+ const regex = new RegExp('^' + pattern.replace(/\*/g, '.*').replace(/\./g, '\\.') + '$');
31
+ return regex.test(filename);
32
+ }
33
+ // Clean root directory
34
+ let deletedCount = 0;
35
+ const files = fs.readdirSync(rootDir);
36
+ for (const file of files) {
37
+ const filePath = path.join(rootDir, file);
38
+ const stat = fs.statSync(filePath);
39
+ if (stat.isDirectory())
40
+ continue;
41
+ for (const pattern of rootPatterns) {
42
+ if (matchesPattern(file, pattern)) {
43
+ if (deleteFile(filePath)) {
44
+ console.log(` ✓ Deleted: ${file}`);
45
+ deletedCount++;
46
+ }
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ console.log(`\n📁 Cleaned ${deletedCount} files from root directory`);
52
+ // Clean Rust build artifacts
53
+ console.log('\n🦀 Cleaning Rust build artifacts...');
54
+ const nativeDir = path.join(rootDir, 'msger-native');
55
+ if (fs.existsSync(nativeDir)) {
56
+ try {
57
+ execSync('cargo clean', {
58
+ cwd: nativeDir,
59
+ stdio: 'inherit'
60
+ });
61
+ console.log(' ✓ Rust artifacts cleaned');
62
+ }
63
+ catch (error) {
64
+ console.error(' ✗ Failed to run cargo clean');
65
+ }
66
+ }
67
+ else {
68
+ console.log(' ⚠️ msger-native directory not found');
69
+ }
70
+ console.log('\n✨ Clean complete!\n');
71
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["clean.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE9B,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAEhD,oCAAoC;AACpC,MAAM,YAAY,GAAG;IACjB,MAAM;IACN,QAAQ;IACR,YAAY;IACZ,UAAU;CACb,CAAC;AAEF,yBAAyB;AACzB,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;AAE7D,SAAS,UAAU,CAAC,QAAgB;IAChC,IAAI,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB,EAAE,OAAe;IACrD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACzF,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,uBAAuB;AACvB,IAAI,YAAY,GAAG,CAAC,CAAC;AACrB,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,WAAW,EAAE;QAAE,SAAS;IAEjC,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACjC,IAAI,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;gBACpC,YAAY,EAAE,CAAC;YACnB,CAAC;YACD,MAAM;QACV,CAAC;IACL,CAAC;AACL,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,4BAA4B,CAAC,CAAC;AAEtE,6BAA6B;AAC7B,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAErD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;IAC3B,IAAI,CAAC;QACD,QAAQ,CAAC,aAAa,EAAE;YACpB,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,SAAS;SACnB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;AACL,CAAC;KAAM,CAAC;IACJ,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AAC1D,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC"}
package/docs/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # msger Documentation
2
+
3
+ ## User Documentation
4
+ - [README.md](../README.md) - Main project README (in root)
5
+ - [MSGER-API.md](MSGER-API.md) - JavaScript API for message box content
6
+ - [MSGER-API-SUMMARY.md](MSGER-API-SUMMARY.md) - Quick API reference
7
+ - [CLOSE-API.md](CLOSE-API.md) - Programmatic close API
8
+
9
+ ## Release Information
10
+ - [CHANGELOG.md](CHANGELOG.md) - Version history and changes
11
+ - [RELEASE-NOTES.md](RELEASE-NOTES.md) - User-facing release notes
12
+ - [KNOWN-BUGS.md](KNOWN-BUGS.md) - Known issues and limitations
13
+
14
+ ## Features
15
+ - [DETACH-FEATURE.md](DETACH-FEATURE.md) - Detached window mode
16
+ - [FULLSCREEN-FEATURE.md](FULLSCREEN-FEATURE.md) - Fullscreen mode
17
+ - [MOUSE-ZOOM-FEATURE.md](MOUSE-ZOOM-FEATURE.md) - Mouse wheel zoom
18
+
19
+ ## Developer Documentation
20
+ - [DEVELOPERS.md](DEVELOPERS.md) - Developer guide
21
+ - [IMPLEMENTATION-SUMMARY.md](IMPLEMENTATION-SUMMARY.md) - Implementation details
22
+ - [PI-RENDERING-NOTES.md](PI-RENDERING-NOTES.md) - Raspberry Pi specific notes
23
+ - [TODO.md](TODO.md) - Future plans and tasks
24
+
25
+ ## Session Notes
26
+ Development session notes are in [sessions/](sessions/)
Binary file
Binary file
Binary file
@@ -0,0 +1,69 @@
1
+ # msger-native Builder
2
+
3
+ Unified build system for msger-native that uses JSON configuration to control which platforms to build.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ cd msger-native
9
+ npm run build
10
+ ```
11
+
12
+ ## Configuration
13
+
14
+ Edit `builder/build-config.json` to control which platforms are built:
15
+
16
+ ```json
17
+ {
18
+ "platforms": {
19
+ "windows": true, // Build Windows x64 binary
20
+ "wsl": false, // Build Linux x64 binary (via WSL)
21
+ "pi": false, // Build Raspberry Pi ARM64 binary (remote build on Pi)
22
+ "arm64": false // Build Linux ARM64 binary (cross-compile via WSL)
23
+ },
24
+ "options": {
25
+ "release": true, // Use release mode (optimized)
26
+ "verbose": false, // Show detailed cargo output
27
+ "piHost": "pi4c", // Raspberry Pi hostname for SSH
28
+ "piProjectPath": "/home/pi/dev/msger/msger-native" // Project path on Pi
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Build Targets
34
+
35
+ | Platform | Output | Method | Requirements |
36
+ |----------|--------|--------|--------------|
37
+ | `windows` | `bin/msgernative.exe` | Native build on Windows | Windows, Visual Studio Build Tools |
38
+ | `wsl` | `bin/msgernative` | Native build in WSL | WSL with Rust toolchain |
39
+ | `pi` | `bin/msgernative-linux-aarch64` | **Remote build on Pi** (slower, guaranteed compatible) | SSH access to Raspberry Pi |
40
+ | `arm64` | `bin/msgernative-linux-aarch64` | **Cross-compile on WSL** (faster, requires setup) | WSL with ARM64 cross-compilation toolchain |
41
+
42
+ **Pi vs ARM64:**
43
+ - **`pi`**: Builds on the actual Raspberry Pi via SSH - slower but guaranteed to work
44
+ - **`arm64`**: Cross-compiles locally using WSL - faster but requires cross-toolchain setup
45
+
46
+ ## Features
47
+
48
+ - **JSON-driven configuration**: Simply edit JSON file to enable/disable platforms
49
+ - **Build summary**: Shows which builds succeeded/failed
50
+ - **Size reporting**: Displays binary size for each platform
51
+ - **TypeScript**: Uses Node's native TypeScript support (no compilation needed)
52
+ - **Conservative defaults**: Only builds Windows by default
53
+
54
+ ## Legacy Scripts
55
+
56
+ The old individual build scripts are still available:
57
+ - `npm run build:legacy` - Original Windows build script
58
+ - `npm run build:wsl` - WSL Linux build
59
+ - `npm run build:pi` - Raspberry Pi build
60
+ - `npm run build:arm64` - ARM64 cross-compile
61
+
62
+ ## Future Enhancements
63
+
64
+ Potential additions:
65
+ - Custom Cargo features/flags configuration
66
+ - Parallel builds
67
+ - Post-build verification/testing
68
+ - Binary signing/notarization
69
+ - Deployment automation
@@ -0,0 +1,14 @@
1
+ {
2
+ "platforms": {
3
+ "windows": true,
4
+ "wsl": false,
5
+ "pi": false,
6
+ "arm64": false
7
+ },
8
+ "options": {
9
+ "release": true,
10
+ "verbose": false,
11
+ "piHost": "pi4c",
12
+ "piProjectPath": "/home/pi/dev/msger/msger-native"
13
+ }
14
+ }
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build script to run natively inside WSL
4
+ * Handles both x64 and ARM64 builds
5
+ * Reads configuration from build-config.json
6
+ *
7
+ * Usage from WSL:
8
+ * node builder/build-under-wsl.ts
9
+ */
10
+
11
+ import { execSync } from 'child_process';
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+
19
+ interface BuildConfig {
20
+ platforms: {
21
+ windows?: boolean;
22
+ wsl?: boolean;
23
+ pi?: boolean;
24
+ arm64?: boolean;
25
+ };
26
+ options?: {
27
+ release?: boolean;
28
+ verbose?: boolean;
29
+ piHost?: string;
30
+ piProjectPath?: string;
31
+ };
32
+ }
33
+
34
+ function timestamp(): string {
35
+ const now = new Date();
36
+ return now.toTimeString().split(' ')[0];
37
+ }
38
+
39
+ interface BuildTarget {
40
+ name: string;
41
+ rustTarget: string;
42
+ outputName: string;
43
+ description: string;
44
+ }
45
+
46
+ const targets: Record<string, BuildTarget> = {
47
+ x64: {
48
+ name: 'x64',
49
+ rustTarget: 'x86_64-unknown-linux-gnu',
50
+ outputName: 'msgernative',
51
+ description: 'Linux x64'
52
+ },
53
+ arm64: {
54
+ name: 'arm64',
55
+ rustTarget: 'aarch64-unknown-linux-gnu',
56
+ outputName: 'msgernative-linux-aarch64',
57
+ description: 'Linux ARM64'
58
+ }
59
+ };
60
+
61
+ function checkToolchain(target: BuildTarget): boolean {
62
+ try {
63
+ const installed = execSync('rustup target list --installed', { encoding: 'utf-8' });
64
+ return installed.includes(target.rustTarget);
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ function installToolchain(target: BuildTarget): boolean {
71
+ console.log(` [${timestamp()}] 📦 Installing ${target.description} toolchain...`);
72
+
73
+ try {
74
+ // Add Rust target
75
+ execSync(`rustup target add ${target.rustTarget}`, { stdio: 'inherit' });
76
+
77
+ // For ARM64, also install cross-compiler
78
+ if (target.name === 'arm64') {
79
+ console.log(` [${timestamp()}] 📦 Installing ARM64 cross-compiler...`);
80
+ execSync('sudo apt update && sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross', {
81
+ stdio: 'inherit'
82
+ });
83
+ }
84
+
85
+ console.log(` [${timestamp()}] ✅ Toolchain installed`);
86
+ return true;
87
+ } catch (error: any) {
88
+ console.error(` [${timestamp()}] ❌ Failed to install toolchain: ${error.message}`);
89
+ return false;
90
+ }
91
+ }
92
+
93
+ function build(target: BuildTarget, verbose: boolean): boolean {
94
+ console.log(`\n[${timestamp()}] 📦 Building ${target.description} binary...`);
95
+
96
+ // Check toolchain
97
+ if (!checkToolchain(target)) {
98
+ console.log(` [${timestamp()}] ⚙️ ${target.description} toolchain not found`);
99
+ if (!installToolchain(target)) {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ const nativeDir = path.join(__dirname, '..');
105
+ const binDir = path.join(nativeDir, 'bin');
106
+ const binaryPath = path.join(binDir, target.outputName);
107
+
108
+ try {
109
+ console.log(` [${timestamp()}] 🔨 Compiling with cargo...`);
110
+ execSync(`cargo build --release --target ${target.rustTarget}`, {
111
+ cwd: nativeDir,
112
+ stdio: verbose ? 'inherit' : 'pipe'
113
+ });
114
+
115
+ // Copy to bin directory
116
+ if (!fs.existsSync(binDir)) {
117
+ fs.mkdirSync(binDir, { recursive: true });
118
+ }
119
+
120
+ const sourcePath = path.join(nativeDir, 'target', target.rustTarget, 'release', 'msgernative');
121
+ fs.copyFileSync(sourcePath, binaryPath);
122
+ fs.chmodSync(binaryPath, 0o755);
123
+
124
+ const stats = fs.statSync(binaryPath);
125
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
126
+ console.log(` [${timestamp()}] ✅ ${target.description} binary completed`);
127
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
128
+ console.log(` [${timestamp()}] 📁 Output: ${binaryPath}`);
129
+ return true;
130
+ } catch (error: any) {
131
+ console.error(` [${timestamp()}] ❌ Build failed: ${error.message}`);
132
+ return false;
133
+ }
134
+ }
135
+
136
+ function loadConfig(): BuildConfig {
137
+ const configPath = path.join(__dirname, 'build-config.json');
138
+
139
+ if (!fs.existsSync(configPath)) {
140
+ console.error('❌ build-config.json not found');
141
+ process.exit(1);
142
+ }
143
+
144
+ try {
145
+ const content = fs.readFileSync(configPath, 'utf-8');
146
+ return JSON.parse(content);
147
+ } catch (error: any) {
148
+ console.error(`❌ Failed to parse build-config.json: ${error.message}`);
149
+ process.exit(1);
150
+ }
151
+ }
152
+
153
+ function main() {
154
+ console.log('🚀 WSL Native Builder\n');
155
+
156
+ const config = loadConfig();
157
+ const verboseFlag = config.options?.verbose ?? false;
158
+
159
+ // Determine which targets to build based on config
160
+ const requestedTargets: string[] = [];
161
+ if (config.platforms.wsl) requestedTargets.push('x64');
162
+ if (config.platforms.arm64) requestedTargets.push('arm64');
163
+
164
+ if (requestedTargets.length === 0) {
165
+ console.log('⚠️ No WSL platforms enabled in build-config.json');
166
+ console.log(' Enable "wsl" for x64 or "arm64" for ARM64 builds');
167
+ process.exit(0);
168
+ }
169
+
170
+ console.log(`📋 Configuration:`);
171
+ console.log(` Mode: ${config.options?.release ? 'release' : 'debug'}`);
172
+ console.log(` Targets: ${requestedTargets.join(', ')}`);
173
+ console.log(` Verbose: ${verboseFlag}\n`);
174
+
175
+ const results: { target: string; success: boolean }[] = [];
176
+
177
+ for (const targetName of requestedTargets) {
178
+ const target = targets[targetName];
179
+ if (!target) {
180
+ console.error(`❌ Unknown target: ${targetName}`);
181
+ console.error(` Available targets: x64, arm64, all`);
182
+ process.exit(1);
183
+ }
184
+
185
+ const success = build(target, verboseFlag);
186
+ results.push({ target: targetName, success });
187
+ }
188
+
189
+ // Summary
190
+ console.log('\n' + '='.repeat(50));
191
+ console.log('📊 Build Summary:');
192
+ console.log('='.repeat(50));
193
+
194
+ for (const result of results) {
195
+ const status = result.success ? '✅' : '❌';
196
+ console.log(`${status} ${result.target}`);
197
+ }
198
+
199
+ const successCount = results.filter(r => r.success).length;
200
+ const totalCount = results.length;
201
+
202
+ console.log('='.repeat(50));
203
+ console.log(`\n🎉 Completed: ${successCount}/${totalCount} builds successful\n`);
204
+
205
+ if (successCount < totalCount) {
206
+ process.exit(1);
207
+ }
208
+ }
209
+
210
+ main();
@@ -0,0 +1,394 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unified build system for msger-native
4
+ * Reads build-config.json to determine which platforms to build
5
+ */
6
+
7
+ import { execSync } from 'child_process';
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { platform } from 'os';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ interface BuildConfig {
17
+ platforms: {
18
+ windows?: boolean;
19
+ wsl?: boolean;
20
+ pi?: boolean;
21
+ arm64?: boolean;
22
+ };
23
+ options?: {
24
+ release?: boolean;
25
+ verbose?: boolean;
26
+ piHost?: string;
27
+ piProjectPath?: string;
28
+ };
29
+ }
30
+
31
+ function isWSL(): boolean {
32
+ try {
33
+ const release = fs.readFileSync('/proc/version', 'utf8');
34
+ return release.toLowerCase().includes('microsoft');
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+
40
+ function isWindows(): boolean {
41
+ return platform() === 'win32' && !isWSL();
42
+ }
43
+
44
+ function getCleanPathForWindows(): string {
45
+ // Remove Git's /usr/bin from PATH to avoid link.exe conflict with VS linker
46
+ const currentPath = process.env.PATH || '';
47
+ const pathParts = currentPath.split(';');
48
+ const filteredParts = pathParts.filter(part => {
49
+ const lower = part.toLowerCase();
50
+ return !lower.includes('git\\usr\\bin') && !lower.includes('git/usr/bin');
51
+ });
52
+ return filteredParts.join(';');
53
+ }
54
+
55
+ function needsRebuild(binaryPath: string, sourceDirs: string[]): boolean {
56
+ if (!fs.existsSync(binaryPath)) {
57
+ return true;
58
+ }
59
+
60
+ const binaryTime = fs.statSync(binaryPath).mtime.getTime();
61
+
62
+ function checkDir(dirPath: string): boolean {
63
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
64
+ for (const entry of entries) {
65
+ const fullPath = path.join(dirPath, entry.name);
66
+ if (entry.isFile()) {
67
+ const fileTime = fs.statSync(fullPath).mtime.getTime();
68
+ if (fileTime > binaryTime) {
69
+ console.log(` 📝 Source file changed: ${entry.name}`);
70
+ return true;
71
+ }
72
+ } else if (entry.isDirectory()) {
73
+ if (checkDir(fullPath)) {
74
+ return true;
75
+ }
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+
81
+ for (const sourcePath of sourceDirs) {
82
+ if (!fs.existsSync(sourcePath)) continue;
83
+
84
+ const stats = fs.statSync(sourcePath);
85
+ if (stats.isFile()) {
86
+ const fileTime = stats.mtime.getTime();
87
+ if (fileTime > binaryTime) {
88
+ console.log(` 📝 Source file changed: ${sourcePath}`);
89
+ return true;
90
+ }
91
+ } else if (stats.isDirectory()) {
92
+ if (checkDir(sourcePath)) {
93
+ return true;
94
+ }
95
+ }
96
+ }
97
+
98
+ return false;
99
+ }
100
+
101
+ /**
102
+ * Load build configuration from JSON file
103
+ */
104
+ function loadConfig(): BuildConfig {
105
+ const configPath = path.join(__dirname, 'build-config.json');
106
+
107
+ if (!fs.existsSync(configPath)) {
108
+ console.error('❌ build-config.json not found');
109
+ process.exit(1);
110
+ }
111
+
112
+ try {
113
+ const content = fs.readFileSync(configPath, 'utf-8');
114
+ return JSON.parse(content);
115
+ } catch (error: any) {
116
+ console.error(`❌ Failed to parse build-config.json: ${error.message}`);
117
+ process.exit(1);
118
+ }
119
+ }
120
+
121
+ function timestamp(): string {
122
+ const now = new Date();
123
+ return now.toTimeString().split(' ')[0]; // HH:MM:SS
124
+ }
125
+
126
+ /**
127
+ * Build Windows binary
128
+ */
129
+ function buildWindows(nativeDir: string, binDir: string, verbose: boolean): boolean {
130
+ console.log(`\n[${timestamp()}] 📦 Building Windows x64 binary...`);
131
+
132
+ const binaryPath = path.join(binDir, 'msgernative.exe');
133
+ const sourceDirs = [
134
+ path.join(nativeDir, 'src'),
135
+ path.join(nativeDir, 'Cargo.toml'),
136
+ path.join(nativeDir, 'build.rs')
137
+ ];
138
+
139
+ if (!needsRebuild(binaryPath, sourceDirs)) {
140
+ console.log(` [${timestamp()}] ✅ Binary is up to date, skipping build`);
141
+ const stats = fs.statSync(binaryPath);
142
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
143
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
144
+ return true;
145
+ }
146
+
147
+ console.log(` [${timestamp()}] 🔧 Fixing PATH to use VS linker instead of Git link.exe`);
148
+ const cleanPath = getCleanPathForWindows();
149
+
150
+ try {
151
+ execSync('cargo build --release', {
152
+ cwd: nativeDir,
153
+ stdio: verbose ? 'inherit' : 'pipe',
154
+ env: { ...process.env, PATH: cleanPath }
155
+ });
156
+
157
+ // Copy to bin directory
158
+ if (!fs.existsSync(binDir)) {
159
+ fs.mkdirSync(binDir, { recursive: true });
160
+ }
161
+
162
+ const sourcePath = path.join(nativeDir, 'target', 'release', 'msgernative.exe');
163
+ fs.copyFileSync(sourcePath, binaryPath);
164
+
165
+ const stats = fs.statSync(binaryPath);
166
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
167
+ console.log(` [${timestamp()}] ✅ Windows x64 binary completed`);
168
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
169
+ return true;
170
+ } catch (error: any) {
171
+ console.error(` [${timestamp()}] ❌ Windows build failed: ${error.message}`);
172
+ return false;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Build WSL Linux binary
178
+ */
179
+ function buildWSL(nativeDir: string, binDir: string, verbose: boolean): boolean {
180
+ console.log(`\n[${timestamp()}] 📦 Building WSL Linux x64 binary...`);
181
+
182
+ const binaryPath = path.join(binDir, 'msgernative');
183
+
184
+ try {
185
+ execSync('wsl bash -c "cd /mnt/y/dev/utils/msger/msger-native && cargo build --release --target x86_64-unknown-linux-gnu"', {
186
+ stdio: verbose ? 'inherit' : 'pipe'
187
+ });
188
+
189
+ // Copy to bin directory
190
+ if (!fs.existsSync(binDir)) {
191
+ fs.mkdirSync(binDir, { recursive: true });
192
+ }
193
+
194
+ const sourcePath = path.join(nativeDir, 'target', 'x86_64-unknown-linux-gnu', 'release', 'msgernative');
195
+ fs.copyFileSync(sourcePath, binaryPath);
196
+ fs.chmodSync(binaryPath, 0o755);
197
+
198
+ const stats = fs.statSync(binaryPath);
199
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
200
+ console.log(` [${timestamp()}] ✅ WSL Linux x64 binary completed`);
201
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
202
+ return true;
203
+ } catch (error: any) {
204
+ console.error(` [${timestamp()}] ❌ WSL build failed: ${error.message}`);
205
+ return false;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Build Raspberry Pi ARM64 binary
211
+ */
212
+ function buildPi(nativeDir: string, binDir: string, verbose: boolean, piHost: string, piProjectPath: string): boolean {
213
+ console.log(`\n[${timestamp()}] 📦 Building Raspberry Pi ARM64 binary...`);
214
+ console.log(` Target: ${piHost}:${piProjectPath}`);
215
+
216
+ const binaryPath = path.join(binDir, 'msgernative-linux-aarch64');
217
+
218
+ try {
219
+ // Build remotely on Pi
220
+ console.log(` [${timestamp()}] 🔗 Building on remote Raspberry Pi...`);
221
+ execSync(`ssh ${piHost} "cd ${piProjectPath} && cargo build --release"`, {
222
+ stdio: verbose ? 'inherit' : 'pipe'
223
+ });
224
+
225
+ // Copy from Pi
226
+ console.log(` [${timestamp()}] 📥 Copying binary from Pi...`);
227
+ if (!fs.existsSync(binDir)) {
228
+ fs.mkdirSync(binDir, { recursive: true });
229
+ }
230
+
231
+ execSync(`scp ${piHost}:${piProjectPath}/target/release/msgernative "${binaryPath}"`, {
232
+ stdio: verbose ? 'inherit' : 'pipe'
233
+ });
234
+
235
+ fs.chmodSync(binaryPath, 0o755);
236
+
237
+ const stats = fs.statSync(binaryPath);
238
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
239
+ console.log(` [${timestamp()}] ✅ Raspberry Pi ARM64 binary completed`);
240
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
241
+ return true;
242
+ } catch (error: any) {
243
+ console.error(` [${timestamp()}] ❌ Pi build failed: ${error.message}`);
244
+ return false;
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Check if ARM64 toolchain is installed
250
+ */
251
+ function checkARM64Toolchain(): boolean {
252
+ try {
253
+ // Check if Rust target is installed
254
+ const targets = execSync('wsl bash -c "rustup target list --installed"', { encoding: 'utf-8' });
255
+ if (!targets.includes('aarch64-unknown-linux-gnu')) {
256
+ return false;
257
+ }
258
+
259
+ // Check if cross-compiler is installed
260
+ const which = execSync('wsl bash -c "which aarch64-linux-gnu-gcc"', { encoding: 'utf-8' });
261
+ return which.trim().length > 0;
262
+ } catch {
263
+ return false;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Install ARM64 toolchain
269
+ */
270
+ function installARM64Toolchain(verbose: boolean): boolean {
271
+ console.log(` [${timestamp()}] 📦 ARM64 toolchain not found, installing...`);
272
+
273
+ try {
274
+ execSync('wsl bash msger-native/pibuild/setup-arm64-toolchain.sh', {
275
+ stdio: verbose ? 'inherit' : 'pipe'
276
+ });
277
+ console.log(` [${timestamp()}] ✅ ARM64 toolchain installed successfully`);
278
+ return true;
279
+ } catch (error: any) {
280
+ console.error(` [${timestamp()}] ❌ Failed to install ARM64 toolchain: ${error.message}`);
281
+ return false;
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Build generic ARM64 binary via cross-compilation
287
+ */
288
+ function buildARM64(nativeDir: string, binDir: string, verbose: boolean): boolean {
289
+ console.log(`\n[${timestamp()}] 📦 Building Linux ARM64 binary (cross-compile)...`);
290
+
291
+ // Check and install toolchain if needed
292
+ if (!checkARM64Toolchain()) {
293
+ console.log(` [${timestamp()}] ⚙️ Checking ARM64 toolchain...`);
294
+ if (!installARM64Toolchain(verbose)) {
295
+ return false;
296
+ }
297
+ }
298
+
299
+ const binaryPath = path.join(binDir, 'msgernative-linux-aarch64');
300
+
301
+ try {
302
+ execSync('wsl bash -c "cd /mnt/y/dev/utils/msger/msger-native && cargo build --release --target aarch64-unknown-linux-gnu"', {
303
+ stdio: verbose ? 'inherit' : 'pipe'
304
+ });
305
+
306
+ // Copy to bin directory
307
+ if (!fs.existsSync(binDir)) {
308
+ fs.mkdirSync(binDir, { recursive: true });
309
+ }
310
+
311
+ const sourcePath = path.join(nativeDir, 'target', 'aarch64-unknown-linux-gnu', 'release', 'msgernative');
312
+ fs.copyFileSync(sourcePath, binaryPath);
313
+ fs.chmodSync(binaryPath, 0o755);
314
+
315
+ const stats = fs.statSync(binaryPath);
316
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
317
+ console.log(` [${timestamp()}] ✅ Linux ARM64 binary completed`);
318
+ console.log(` [${timestamp()}] 📊 Binary size: ${sizeMB} MB`);
319
+ return true;
320
+ } catch (error: any) {
321
+ console.error(` [${timestamp()}] ❌ ARM64 build failed: ${error.message}`);
322
+ return false;
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Main build orchestrator
328
+ */
329
+ function main() {
330
+ console.log('🚀 msger-native unified builder\n');
331
+
332
+ const config = loadConfig();
333
+ const verbose = config.options?.verbose ?? false;
334
+ const release = config.options?.release ?? true;
335
+
336
+ const nativeDir = path.join(__dirname, '..');
337
+ const binDir = path.join(nativeDir, 'bin');
338
+
339
+ const enabledPlatforms = Object.entries(config.platforms)
340
+ .filter(([_, enabled]) => enabled)
341
+ .map(([name]) => name);
342
+
343
+ console.log(`📋 Build configuration:`);
344
+ console.log(` Mode: ${release ? 'release' : 'debug'}`);
345
+ console.log(` Platforms: ${enabledPlatforms.join(', ') || 'none'}\n`);
346
+
347
+ if (enabledPlatforms.length === 0) {
348
+ console.log('⚠️ No platforms enabled in build-config.json');
349
+ process.exit(0);
350
+ }
351
+
352
+ const results: { platform: string; success: boolean }[] = [];
353
+
354
+ // Build each enabled platform
355
+ if (config.platforms.windows) {
356
+ results.push({ platform: 'windows', success: buildWindows(nativeDir, binDir, verbose) });
357
+ }
358
+
359
+ if (config.platforms.wsl) {
360
+ results.push({ platform: 'wsl', success: buildWSL(nativeDir, binDir, verbose) });
361
+ }
362
+
363
+ if (config.platforms.pi) {
364
+ const piHost = config.options?.piHost ?? 'pi4c';
365
+ const piProjectPath = config.options?.piProjectPath ?? '/home/pi/dev/msger/msger-native';
366
+ results.push({ platform: 'pi', success: buildPi(nativeDir, binDir, verbose, piHost, piProjectPath) });
367
+ }
368
+
369
+ if (config.platforms.arm64) {
370
+ results.push({ platform: 'arm64', success: buildARM64(nativeDir, binDir, verbose) });
371
+ }
372
+
373
+ // Summary
374
+ console.log('\n' + '='.repeat(50));
375
+ console.log('📊 Build Summary:');
376
+ console.log('='.repeat(50));
377
+
378
+ for (const result of results) {
379
+ const status = result.success ? '✅' : '❌';
380
+ console.log(`${status} ${result.platform}`);
381
+ }
382
+
383
+ const successCount = results.filter(r => r.success).length;
384
+ const totalCount = results.length;
385
+
386
+ console.log('='.repeat(50));
387
+ console.log(`\n🎉 Completed: ${successCount}/${totalCount} builds successful\n`);
388
+
389
+ if (successCount < totalCount) {
390
+ process.exit(1);
391
+ }
392
+ }
393
+
394
+ main();
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Cross-platform clean script
4
+ * Removes build artifacts
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import { execSync } from 'child_process';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ // Navigate to project root (two levels up from builder/)
16
+ const rootDir = path.join(__dirname, '../..');
17
+
18
+ console.log('🧹 Cleaning build artifacts...\n');
19
+
20
+ // Files to delete in root directory
21
+ const rootPatterns = [
22
+ '*.js',
23
+ '*.d.ts',
24
+ '*.d.ts.map',
25
+ '*.js.map'
26
+ ];
27
+
28
+ // Directories to exclude
29
+ const excludeDirs = ['node_modules', '.git', 'msger-native'];
30
+
31
+ function deleteFile(filePath: string): boolean {
32
+ try {
33
+ fs.unlinkSync(filePath);
34
+ return true;
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+
40
+ function matchesPattern(filename: string, pattern: string): boolean {
41
+ const regex = new RegExp('^' + pattern.replace(/\*/g, '.*').replace(/\./g, '\\.') + '$');
42
+ return regex.test(filename);
43
+ }
44
+
45
+ // Clean root directory
46
+ let deletedCount = 0;
47
+ const files = fs.readdirSync(rootDir);
48
+
49
+ for (const file of files) {
50
+ const filePath = path.join(rootDir, file);
51
+ const stat = fs.statSync(filePath);
52
+
53
+ if (stat.isDirectory()) continue;
54
+
55
+ for (const pattern of rootPatterns) {
56
+ if (matchesPattern(file, pattern)) {
57
+ if (deleteFile(filePath)) {
58
+ console.log(` ✓ Deleted: ${file}`);
59
+ deletedCount++;
60
+ }
61
+ break;
62
+ }
63
+ }
64
+ }
65
+
66
+ console.log(`\n📁 Cleaned ${deletedCount} files from root directory`);
67
+
68
+ // Clean Rust build artifacts
69
+ console.log('\n🦀 Cleaning Rust build artifacts...');
70
+ const nativeDir = path.join(rootDir, 'msger-native');
71
+
72
+ if (fs.existsSync(nativeDir)) {
73
+ try {
74
+ execSync('cargo clean', {
75
+ cwd: nativeDir,
76
+ stdio: 'inherit'
77
+ });
78
+ console.log(' ✓ Rust artifacts cleaned');
79
+ } catch (error) {
80
+ console.error(' ✗ Failed to run cargo clean');
81
+ }
82
+ } else {
83
+ console.log(' ⚠️ msger-native directory not found');
84
+ }
85
+
86
+ console.log('\n✨ Clean complete!\n');
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script to set executable permissions on Linux binaries
4
+ * and check for required system dependencies
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import { execSync } from 'child_process';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ function detectDistro(): string {
16
+ if (!fs.existsSync('/etc/os-release')) {
17
+ return 'unknown';
18
+ }
19
+
20
+ try {
21
+ const osRelease = fs.readFileSync('/etc/os-release', 'utf8').toLowerCase();
22
+
23
+ if (osRelease.includes('ubuntu') || osRelease.includes('debian')) {
24
+ return 'debian';
25
+ }
26
+ if (osRelease.includes('fedora') || osRelease.includes('rhel') || osRelease.includes('centos')) {
27
+ return 'fedora';
28
+ }
29
+ if (osRelease.includes('arch')) {
30
+ return 'arch';
31
+ }
32
+
33
+ return 'unknown';
34
+ } catch {
35
+ return 'unknown';
36
+ }
37
+ }
38
+
39
+ function showDependencyInstallCommand(distro: string): void {
40
+ console.warn('\n⚠️ Missing system dependencies detected!');
41
+ console.warn(' Install required libraries with:\n');
42
+
43
+ switch (distro) {
44
+ case 'debian':
45
+ console.warn(' sudo apt update');
46
+ console.warn(' sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0\n');
47
+ break;
48
+ case 'fedora':
49
+ console.warn(' sudo dnf install webkit2gtk4.1 gtk3\n');
50
+ break;
51
+ case 'arch':
52
+ console.warn(' sudo pacman -S webkit2gtk gtk3\n');
53
+ break;
54
+ default:
55
+ console.warn(' Install webkit2gtk and gtk3 for your distribution\n');
56
+ }
57
+ }
58
+
59
+ function checkSystemDependencies(binaryPath: string): void {
60
+ try {
61
+ const lddOutput = execSync(`ldd "${binaryPath}" 2>&1`, { encoding: 'utf8' });
62
+
63
+ if (lddOutput.includes('not found')) {
64
+ const distro = detectDistro();
65
+ showDependencyInstallCommand(distro);
66
+ }
67
+ } catch {
68
+ // ldd command failed or not installed - skip check
69
+ }
70
+ }
71
+
72
+ function setExecutePermissions(binaryPath: string, binaryName: string): void {
73
+ try {
74
+ fs.chmodSync(binaryPath, 0o755);
75
+ console.log(`✅ Set execute permissions on ${binaryName} binary`);
76
+ } catch (error: any) {
77
+ console.warn(`⚠️ Could not set execute permission on ${binaryPath}: ${error.message}`);
78
+ console.warn(` You may need to run: sudo chmod +x ${binaryPath}`);
79
+ }
80
+ }
81
+
82
+ function main(): void {
83
+ // Windows doesn't need executable permissions
84
+ if (process.platform === 'win32') {
85
+ return;
86
+ }
87
+
88
+ // Determine binary name based on architecture
89
+ const arch = process.arch;
90
+ const binaryName = arch === 'arm64' ? 'msgernative-linux-aarch64' : 'msgernative';
91
+ const binaryPath = path.join(__dirname, '..', 'bin', binaryName);
92
+
93
+ // Binary doesn't exist - warn user
94
+ if (!fs.existsSync(binaryPath)) {
95
+ console.warn(`⚠️ Binary not found at ${binaryPath}`);
96
+ console.warn(` The msger package may not support your platform (${process.platform} ${arch})`);
97
+ return;
98
+ }
99
+
100
+ // Set executable permissions
101
+ setExecutePermissions(binaryPath, binaryName);
102
+
103
+ // Check for required system libraries
104
+ checkSystemDependencies(binaryPath);
105
+ }
106
+
107
+ main();
@@ -4,10 +4,7 @@
4
4
  "description": "Rust binary for msger - native message box implementation",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build": "node build.ts",
8
- "build:wsl": "node build-wsl.ts",
9
- "build:arm64": "node build-arm64.ts",
10
- "build:pi": "node build-pi.ts"
7
+ "build": "node builder/builder.ts"
11
8
  },
12
9
  "keywords": [
13
10
  "message-box",
@@ -0,0 +1,42 @@
1
+ # Raspberry Pi Build Utilities
2
+
3
+ Utilities for building msger-native on Raspberry Pi (ARM64/aarch64).
4
+
5
+ ## Files
6
+
7
+ ### build-on-pi.sh
8
+ Shell script to run on the Raspberry Pi itself to build the native binary.
9
+
10
+ ### build-pi.ps1
11
+ PowerShell script to build remotely on Pi via SSH (called from Windows).
12
+
13
+ ### pi-diagnostics.ts
14
+ TypeScript diagnostic script to check Pi build environment and dependencies.
15
+
16
+ ### setup-arm64-toolchain.sh
17
+ Sets up ARM64 cross-compilation toolchain on WSL for local ARM64 builds.
18
+
19
+ ## Usage
20
+
21
+ The main builder (`../builder/builder.ts`) handles Pi builds automatically when enabled in `build-config.json`. These utilities are for manual builds or troubleshooting.
22
+
23
+ ### Remote build on Pi (from Windows):
24
+ ```powershell
25
+ .\build-pi.ps1
26
+ ```
27
+
28
+ ### Direct build on Pi:
29
+ ```bash
30
+ ssh pi4c
31
+ cd /home/pi/dev/msger/msger-native
32
+ ./pibuild/build-on-pi.sh
33
+ ```
34
+
35
+ ### Setup ARM64 cross-compilation:
36
+ ```bash
37
+ wsl bash pibuild/setup-arm64-toolchain.sh
38
+ ```
39
+
40
+ ## Output
41
+
42
+ Pi builds produce: `bin/msgernative-linux-aarch64`
@@ -170,15 +170,16 @@ fn default_title() -> String {
170
170
  }
171
171
 
172
172
  fn get_package_version() -> Option<String> {
173
- // Read ../package.json relative to executable
173
+ // Read version from parent package.json (not msger-native/package.json)
174
174
  let exe_path = std::env::current_exe().ok()?;
175
175
  let exe_dir = exe_path.parent()?;
176
176
 
177
177
  // Try multiple possible locations for package.json
178
+ // NOTE: Check ../../package.json FIRST to skip msger-native/package.json
178
179
  let possible_paths = vec![
179
- exe_dir.join("../package.json"), // Development: bin/../package.json
180
- exe_dir.join("../../package.json"), // Installed globally: lib/node_modules/@bobfrankston/msger/package.json
181
- exe_dir.join("../../../package.json"), // node_modules structure
180
+ exe_dir.join("../../package.json"), // Development: bin/../../package.json (parent of msger-native)
181
+ exe_dir.join("../../../package.json"), // Installed globally: lib/node_modules/@bobfrankston/msger/package.json
182
+ exe_dir.join("../../../../package.json"), // Deeply nested node_modules
182
183
  ];
183
184
 
184
185
  for path in possible_paths {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/msger",
3
- "version": "0.1.128",
3
+ "version": "0.1.130",
4
4
  "description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -16,19 +16,14 @@
16
16
  "scripts": {
17
17
  "build": "npm run build:ts && npm run build:native",
18
18
  "build:native": "cd msger-native && npm run build",
19
- "build:native:wsl": "cd msger-native && npm run build:wsl",
20
- "build:native:arm64": "cd msger-native && npm run build:arm64",
21
- "build:native:pi": "cd msger-native && npm run build:pi",
22
- "build:native:all": "npm run build:native && npm run build:native:wsl && (npm run build:native:pi || true)",
23
- "setup:arm64": "wsl bash msger-native/setup-arm64-toolchain.sh",
24
19
  "build:ts": "tsc",
25
20
  "watch": "tsc -w",
26
- "clean": "rm -rf *.js *.d.ts *.js.map bin && cd msger-native && cargo clean",
21
+ "clean": "node msger-native/builder/clean.ts",
27
22
  "test": "node test.js",
28
- "postinstall": "node postinstall.js",
29
- "prepublishOnly": "npm run build:ts && npm run build:native:all",
23
+ "postinstall": "node msger-native/builder/postinstall.ts",
24
+ "prepublishOnly": "npm run build:ts && npm run build:native",
30
25
  "prerelease:local": "git add -A && (git diff-index --quiet HEAD || git commit -m \"Pre-release commit\")",
31
- "preversion": "npm run build:ts && npm run build:native:all && git add -A",
26
+ "preversion": "npm run build:ts && npm run build:native && git add -A",
32
27
  "postversion": "git push && git push --tags",
33
28
  "release": "npm run prerelease:local && npm version patch && npm publish",
34
29
  "installer": "npm run release && npm cache clean --force && npm install -g @bobfrankston/msger@latest && wsl npm cache clean --force && wsl npm install -g @bobfrankston/msger@latest"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes