seabox 0.1.0-beta.3 → 0.1.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.
package/bin/seabox.mjs ADDED
@@ -0,0 +1,147 @@
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,10 +1,15 @@
1
1
  /**
2
- * blob.js
2
+ * blob.mjs
3
3
  * Create SEA configuration JSON and prepare blob for injection.
4
4
  */
5
5
 
6
- const fs = require('fs');
7
- const path = require('path');
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { execFile } from 'child_process';
9
+ import { promisify } from 'util';
10
+ import * as diag from './diagnostics.mjs';
11
+
12
+ const execFileAsync = promisify(execFile);
8
13
 
9
14
  /**
10
15
  * @typedef {Object} SeaBlobConfig
@@ -20,11 +25,11 @@ const path = require('path');
20
25
  * Create the SEA configuration object for Node.js SEA tooling.
21
26
  * @param {string} entryScript - Path to the bundled entry script
22
27
  * @param {string} outputBlob - Output blob filename
23
- * @param {import('./scanner').AssetEntry[]} assets - All assets to embed
28
+ * @param {Array} assets - All assets to embed
24
29
  * @param {Object} config - SEA configuration
25
30
  * @returns {SeaBlobConfig}
26
31
  */
27
- function createSeaConfig(entryScript, outputBlob, assets, config) {
32
+ export function createSeaConfig(entryScript, outputBlob, assets, config) {
28
33
  const seaConfig = {
29
34
  main: entryScript,
30
35
  output: outputBlob,
@@ -51,10 +56,10 @@ function createSeaConfig(entryScript, outputBlob, assets, config) {
51
56
  * This config file is consumed by `node --experimental-sea-config`.
52
57
  * @param {SeaBlobConfig} seaConfig
53
58
  * @param {string} outputPath - Path to write the config JSON
54
- * @param {import('./scanner').AssetEntry[]} assets - Original asset entries
59
+ * @param {Array} assets - Original asset entries
55
60
  * @param {string} tempDir - Temporary directory for inline assets
56
61
  */
57
- function writeSeaConfigJson(seaConfig, outputPath, assets, tempDir) {
62
+ export function writeSeaConfigJson(seaConfig, outputPath, assets, tempDir) {
58
63
  // Node's SEA config expects asset values to be file paths (raw assets)
59
64
  const jsonConfig = {
60
65
  main: seaConfig.main,
@@ -89,21 +94,11 @@ function writeSeaConfigJson(seaConfig, outputPath, assets, tempDir) {
89
94
  * @param {string} nodeBinary - Path to the Node.js binary to use
90
95
  * @returns {Promise<void>}
91
96
  */
92
- async function generateBlob(seaConfigPath, nodeBinary = process.execPath) {
93
- const { execFile } = require('child_process');
94
- const { promisify } = require('util');
95
- const execFileAsync = promisify(execFile);
96
-
97
+ export async function generateBlob(seaConfigPath, nodeBinary = process.execPath) {
97
98
  try {
98
99
  await execFileAsync(nodeBinary, ['--experimental-sea-config', seaConfigPath]);
99
- console.log('SEA blob generated successfully');
100
+ diag.verbose('SEA blob generated successfully', 2);
100
101
  } catch (error) {
101
102
  throw new Error(`Failed to generate SEA blob: ${error.message}`);
102
103
  }
103
104
  }
104
-
105
- module.exports = {
106
- createSeaConfig,
107
- writeSeaConfigJson,
108
- generateBlob
109
- };