seabox 0.1.2 → 0.3.0

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,88 +1,107 @@
1
- #!/usr/bin/env node
2
- /**
3
- * seabox-rebuild.mjs
4
- * Rebuild native modules for target platform/architecture
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 * as diag from '../lib/diagnostics.mjs';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
-
16
- /**
17
- * Rebuild a native module for a specific target
18
- * @param {string} modulePath - Path to the native module
19
- * @param {string} platform - Target platform (win32, linux, darwin)
20
- * @param {string} arch - Target architecture (x64, arm64)
21
- * @param {boolean} verbose - Enable verbose logging
22
- */
23
- function rebuildNativeModule(modulePath, platform, arch, verbose = false) {
24
- diag.setVerbose(verbose);
25
-
26
- diag.verbose(`Rebuilding native module: ${modulePath}`);
27
- diag.verbose(`Target: ${platform}-${arch}`);
28
-
29
- const packageJsonPath = path.join(modulePath, 'package.json');
30
- if (!fs.existsSync(packageJsonPath)) {
31
- throw new Error(`No package.json found in ${modulePath}`);
32
- }
33
-
34
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
35
- const moduleName = pkg.name;
36
-
37
- // Check if module has native bindings
38
- const hasBindingGyp = fs.existsSync(path.join(modulePath, 'binding.gyp'));
39
- if (!hasBindingGyp && !pkg.gypfile) {
40
- diag.verbose(`Module ${moduleName} does not appear to have native bindings, skipping`);
41
- return;
42
- }
43
-
44
- try {
45
- // Use node-gyp to rebuild for the target platform
46
- const cmd = `npx node-gyp rebuild --target_platform=${platform} --target_arch=${arch}`;
47
-
48
- diag.verbose(`Running: ${cmd}`);
49
-
50
- execSync(cmd, {
51
- cwd: modulePath,
52
- stdio: verbose ? 'inherit' : 'pipe',
53
- env: {
54
- ...process.env,
55
- npm_config_target_platform: platform,
56
- npm_config_target_arch: arch
57
- }
58
- });
59
-
60
- diag.verbose(`Successfully rebuilt ${moduleName}`);
61
- } catch (error) {
62
- diag.verbose(`Failed to rebuild ${moduleName}: ${error.message}`);
63
- throw error;
64
- }
65
- }
66
-
67
- // CLI entry point
68
- if (import.meta.url === `file://${process.argv[1]}`) {
69
- const args = process.argv.slice(2);
70
-
71
- if (args.length < 3) {
72
- diag.error('Usage: seabox-rebuild <module-path> <platform> <arch> [--verbose]');
73
- process.exit(1);
74
- }
75
-
76
- const [modulePath, platform, arch] = args;
77
- const verbose = args.includes('--verbose') || args.includes('-v');
78
-
79
- try {
80
- rebuildNativeModule(modulePath, platform, arch, verbose);
81
- process.exit(0);
82
- } catch (error) {
83
- diag.error(`Rebuild failed: ${error.message}`);
84
- process.exit(1);
85
- }
86
- }
87
-
88
- export { rebuildNativeModule };
1
+ #!/usr/bin/env node
2
+ /**
3
+ * seabox-rebuild.mjs
4
+ * Rebuild native modules for target platform/architecture
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 * as diag from '../lib/diagnostics.mjs';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ /**
17
+ * Rebuild a native module for a specific target
18
+ * @param {string} modulePath - Path to the native module
19
+ * @param {string} nodeVersion - Target Node.js version (e.g., "24.13.0")
20
+ * @param {string} platform - Target platform (win32, linux, darwin)
21
+ * @param {string} arch - Target architecture (x64, arm64)
22
+ * @param {boolean} verbose - Enable verbose logging
23
+ */
24
+ function rebuildNativeModule(modulePath, nodeVersion, platform, arch, verbose = false) {
25
+ diag.setVerbose(verbose);
26
+
27
+ diag.verbose(`Rebuilding native module: ${modulePath}`);
28
+ diag.verbose(`Target: Node.js ${nodeVersion} ${platform}-${arch}`);
29
+
30
+ const packageJsonPath = path.join(modulePath, 'package.json');
31
+ if (!fs.existsSync(packageJsonPath)) {
32
+ throw new Error(`No package.json found in ${modulePath}`);
33
+ }
34
+
35
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
36
+ const moduleName = pkg.name;
37
+
38
+ // Check if module has native bindings
39
+ const hasBindingGyp = fs.existsSync(path.join(modulePath, 'binding.gyp'));
40
+ if (!hasBindingGyp && !pkg.gypfile) {
41
+ diag.verbose(`Module ${moduleName} does not appear to have native bindings, skipping`);
42
+ return;
43
+ }
44
+
45
+ try {
46
+ // Use node-gyp to rebuild for the target Node.js version, platform, and architecture
47
+ // --target specifies the Node.js version (critical for NODE_MODULE_VERSION)
48
+ // --dist-url ensures node-gyp downloads headers from the correct location
49
+ const cmd = `npx node-gyp rebuild --target=${nodeVersion} --arch=${arch} --dist-url=https://nodejs.org/dist`;
50
+
51
+ diag.verbose(`Building for Node.js ${nodeVersion} (${platform}-${arch})`, 2);
52
+ diag.verbose(`Command: ${cmd}`, 2);
53
+
54
+ execSync(cmd, {
55
+ cwd: modulePath,
56
+ stdio: 'pipe', // Hide output unless error occurs
57
+ env: {
58
+ ...process.env,
59
+ npm_config_target: nodeVersion,
60
+ npm_config_arch: arch,
61
+ npm_config_target_arch: arch,
62
+ npm_config_disturl: 'https://nodejs.org/dist'
63
+ }
64
+ });
65
+
66
+ diag.verbose(`Successfully built for Node.js ${nodeVersion}`, 2);
67
+ } catch (error) {
68
+ // Show node-gyp output on error
69
+ if (error.stdout) console.error(error.stdout.toString());
70
+ if (error.stderr) console.error(error.stderr.toString());
71
+ diag.verbose(`Failed to rebuild ${moduleName}: ${error.message}`);
72
+ throw error;
73
+ }
74
+ }
75
+
76
+ // CLI entry point - compare normalized paths for cross-platform compatibility
77
+ const isMainModule = (() => {
78
+ try {
79
+ const scriptPath = fileURLToPath(import.meta.url);
80
+ const argPath = path.resolve(process.argv[1]);
81
+ return scriptPath === argPath;
82
+ } catch {
83
+ return false;
84
+ }
85
+ })();
86
+
87
+ if (isMainModule) {
88
+ const args = process.argv.slice(2);
89
+
90
+ if (args.length < 4) {
91
+ diag.error('Usage: seabox-rebuild <module-path> <node-version> <platform> <arch> [--verbose]');
92
+ process.exit(1);
93
+ }
94
+
95
+ const [modulePath, nodeVersion, platform, arch] = args;
96
+ const verbose = args.includes('--verbose') || args.includes('-v');
97
+
98
+ try {
99
+ rebuildNativeModule(modulePath, nodeVersion, platform, arch, verbose);
100
+ process.exit(0);
101
+ } catch (error) {
102
+ diag.error(`Rebuild failed: ${error.message}`);
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+ export { rebuildNativeModule };
package/bin/seabox.mjs CHANGED
@@ -1,147 +1,150 @@
1
- #!/usr/bin/env node
2
- /**
3
- * seabox.mjs
4
- * CLI entry point for Seabox architecture (testing/development)
5
- *
6
- * Usage:
7
- * seabox build [--config path] [--verbose]
8
- */
9
-
10
- import path from 'path';
11
- import fs from 'fs';
12
- import { fileURLToPath } from 'url';
13
- import Module from 'module';
14
- import * as diag from '../lib/diagnostics.mjs';
15
-
16
- const __filename = fileURLToPath(import.meta.url);
17
- const __dirname = path.dirname(__filename);
18
-
19
- const commands = {
20
- build: async (args) => {
21
- const { loadConfig } = await import('../lib/config.mjs');
22
-
23
- const configPath = args.includes('--config') ? args[args.indexOf('--config') + 1] : null;
24
- const projectRoot = process.cwd();
25
-
26
- // Check if config exists before attempting build
27
- const config = loadConfig(configPath, projectRoot);
28
-
29
- if (!config) {
30
- diag.error('No configuration found');
31
- diag.separator();
32
- diag.info('Seabox looks for configuration in this order:');
33
- diag.numberedItem(1, '--config <path> (command line argument)');
34
- diag.numberedItem(2, 'seabox.config.json (in current directory)');
35
- diag.numberedItem(3, '"seabox" field in package.json');
36
- diag.separator();
37
- diag.info('To get started, run: npx seabox init');
38
- diag.separator();
39
- commands.help();
40
- process.exit(1);
41
- }
42
-
43
- const { build } = await import('../lib/build.mjs');
44
-
45
- const options = {
46
- configPath,
47
- verbose: args.includes('--verbose') || args.includes('-v'),
48
- debug: args.includes('--debug'),
49
- projectRoot
50
- };
51
-
52
- await build(options);
53
- },
54
-
55
- migrate: async (args) => {
56
- // Use CommonJS require for the migration tool
57
- const require = Module.createRequire(import.meta.url);
58
- const { migrate } = require('./seabox-migrate.js');
59
- await migrate();
60
- },
61
-
62
- init: async (args) => {
63
- const { generateDefaultConfig } = await import('../lib/config.mjs');
64
-
65
- const configPath = path.join(process.cwd(), 'seabox.config.json');
66
-
67
- if (fs.existsSync(configPath)) {
68
- diag.error('seabox.config.json already exists');
69
- process.exit(1);
70
- }
71
-
72
- const defaultConfig = generateDefaultConfig({
73
- entry: './src/index.js'
74
- });
75
-
76
- fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
77
-
78
- diag.success('Created seabox.config.json', 0);
79
- diag.separator();
80
- diag.info('Next steps:');
81
- diag.numberedItem(1, 'Edit seabox.config.json to configure your build');
82
- diag.numberedItem(2, 'Run: npx seabox build');
83
- diag.separator();
84
- },
85
-
86
- help: () => {
87
- diag.info('Seabox v2 - Node.js Single Executable Application Builder');
88
- diag.separator();
89
- diag.info('Usage: seabox [command] [options]');
90
- diag.separator();
91
- diag.info('Commands:');
92
- diag.info(' build Build executable(s) for configured targets (default)');
93
- diag.info(' init Create a default seabox.config.json');
94
- diag.separator();
95
- diag.info('Build Options:');
96
- diag.info(' --config Path to config file (default: seabox.config.json)');
97
- diag.info(' --verbose Enable verbose logging');
98
- diag.info(' --debug Keep temporary build files');
99
- diag.separator();
100
- diag.info('Examples:');
101
- diag.info(' seabox init');
102
- diag.info(' seabox build');
103
- diag.info(' seabox --verbose # Same as: seabox build --verbose');
104
- diag.info(' seabox build --verbose');
105
- diag.separator();
106
- }
107
- };
108
-
109
- async function main() {
110
- const args = process.argv.slice(2);
111
-
112
- // If no args or first arg is a flag, default to help
113
- if (args.length === 0) {
114
- commands.help();
115
- return;
116
- }
117
-
118
- // Check if first arg is a flag (starts with --)
119
- const firstArg = args[0];
120
- let command = firstArg;
121
- let commandArgs = args.slice(1);
122
-
123
- if (firstArg.startsWith('-')) {
124
- // First arg is a flag, so default to 'build' command
125
- command = 'build';
126
- commandArgs = args; // Include all args including the flags
127
- }
128
-
129
- if (commands[command]) {
130
- try {
131
- await commands[command](commandArgs);
132
- } catch (error) {
133
- diag.error(error.message);
134
- if (args.includes('--verbose')) {
135
- console.error(error.stack);
136
- }
137
- process.exit(1);
138
- }
139
- } else {
140
- diag.error(`Unknown command: ${command}`);
141
- diag.separator();
142
- commands.help();
143
- process.exit(1);
144
- }
145
- }
146
-
147
- main();
1
+ #!/usr/bin/env node
2
+ /**
3
+ * seabox.mjs
4
+ * CLI entry point for Seabox architecture (testing/development)
5
+ *
6
+ * Usage:
7
+ * seabox build [--config path] [--verbose]
8
+ */
9
+
10
+ import path from 'path';
11
+ import fs from 'fs';
12
+ import { fileURLToPath } from 'url';
13
+ import Module from 'module';
14
+ import * as diag from '../lib/diagnostics.mjs';
15
+ import { createRequire } from 'module';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = path.dirname(__filename);
19
+ const require = createRequire(import.meta.url);
20
+ const pkg = require('../package.json');
21
+
22
+ const commands = {
23
+ build: async (args) => {
24
+ const { loadConfig } = await import('../lib/config.mjs');
25
+
26
+ const configPath = args.includes('--config') ? args[args.indexOf('--config') + 1] : null;
27
+ const projectRoot = process.cwd();
28
+
29
+ // Check if config exists before attempting build
30
+ const config = loadConfig(configPath, projectRoot);
31
+
32
+ if (!config) {
33
+ diag.error('No configuration found');
34
+ diag.separator();
35
+ diag.info('Seabox looks for configuration in this order:');
36
+ diag.numberedItem(1, '--config <path> (command line argument)');
37
+ diag.numberedItem(2, 'seabox.config.json (in current directory)');
38
+ diag.numberedItem(3, '"seabox" field in package.json');
39
+ diag.separator();
40
+ diag.info('To get started, run: npx seabox init');
41
+ diag.separator();
42
+ commands.help();
43
+ process.exit(1);
44
+ }
45
+
46
+ const { build } = await import('../lib/build.mjs');
47
+
48
+ const options = {
49
+ configPath,
50
+ verbose: args.includes('--verbose') || args.includes('-v'),
51
+ debug: args.includes('--debug'),
52
+ projectRoot
53
+ };
54
+
55
+ await build(options);
56
+ },
57
+
58
+ migrate: async (args) => {
59
+ // Use CommonJS require for the migration tool
60
+ const require = Module.createRequire(import.meta.url);
61
+ const { migrate } = require('./seabox-migrate.js');
62
+ await migrate();
63
+ },
64
+
65
+ init: async (args) => {
66
+ const { generateDefaultConfig } = await import('../lib/config.mjs');
67
+
68
+ const configPath = path.join(process.cwd(), 'seabox.config.json');
69
+
70
+ if (fs.existsSync(configPath)) {
71
+ diag.error('seabox.config.json already exists');
72
+ process.exit(1);
73
+ }
74
+
75
+ const defaultConfig = generateDefaultConfig({
76
+ entry: './src/index.js'
77
+ });
78
+
79
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
80
+
81
+ diag.success('Created seabox.config.json', 0);
82
+ diag.separator();
83
+ diag.info('Next steps:');
84
+ diag.numberedItem(1, 'Edit seabox.config.json to configure your build');
85
+ diag.numberedItem(2, 'Run: npx seabox build');
86
+ diag.separator();
87
+ },
88
+
89
+ help: () => {
90
+ diag.info('Usage: seabox [command] [options]');
91
+ diag.separator();
92
+ diag.info('Commands:');
93
+ diag.info(' build Build executable(s) for configured targets (default)');
94
+ diag.info(' init Create a default seabox.config.json');
95
+ diag.separator();
96
+ diag.info('Build Options:');
97
+ diag.info(' --config Path to config file (default: seabox.config.json)');
98
+ diag.info(' --verbose Enable verbose logging');
99
+ diag.info(' --debug Keep temporary build files');
100
+ diag.separator();
101
+ diag.info('Examples:');
102
+ diag.info(' seabox init');
103
+ diag.info(' seabox build');
104
+ diag.info(' seabox --verbose # Same as: seabox build --verbose');
105
+ diag.info(' seabox build --verbose');
106
+ diag.separator();
107
+ }
108
+ };
109
+
110
+ async function main() {
111
+ console.log(`Seabox v${pkg.version}`);
112
+
113
+ const args = process.argv.slice(2);
114
+
115
+ // If no args or first arg is a flag, default to help
116
+ if (args.length === 0) {
117
+ commands.help();
118
+ return;
119
+ }
120
+
121
+ // Check if first arg is a flag (starts with --)
122
+ const firstArg = args[0];
123
+ let command = firstArg;
124
+ let commandArgs = args.slice(1);
125
+
126
+ if (firstArg.startsWith('-')) {
127
+ // First arg is a flag, so default to 'build' command
128
+ command = 'build';
129
+ commandArgs = args; // Include all args including the flags
130
+ }
131
+
132
+ if (commands[command]) {
133
+ try {
134
+ await commands[command](commandArgs);
135
+ } catch (error) {
136
+ diag.error(error.message);
137
+ if (args.includes('--verbose')) {
138
+ console.error(error.stack);
139
+ }
140
+ process.exit(1);
141
+ }
142
+ } else {
143
+ diag.error(`Unknown command: ${command}`);
144
+ diag.separator();
145
+ commands.help();
146
+ process.exit(1);
147
+ }
148
+ }
149
+
150
+ main();