@codemoreira/esad 1.3.6 → 1.3.8

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/esad.js CHANGED
@@ -1,77 +1,89 @@
1
1
  #!/usr/bin/env node
2
-
3
- const { program } = require('commander');
4
- const pkg = require('../package.json');
5
-
6
- // Import Commands
7
- const initCommand = require('../src/cli/commands/init');
8
- const createModuleCommand = require('../src/cli/commands/createModule');
9
- const createCdnCommand = require('../src/cli/commands/createCdn');
10
- const deployCommand = require('../src/cli/commands/deploy');
11
- const devCommand = require('../src/cli/commands/dev');
12
- const hostCommand = require('../src/cli/commands/host');
13
-
14
- program
15
- .version(pkg.version)
16
- .description('esad - Easy Super App Development Toolkit');
17
-
18
- // --- COMMMAND: esad init ---
19
- program
20
- .command('init <project-name>')
21
- .description('Scaffold a new ESAD workspace containing the Host App')
22
- .action(async (name) => {
23
- await initCommand(name);
24
- process.exit(0);
25
- });
26
-
27
- // --- COMMAND: esad create-cdn ---
28
- program
29
- .command('create-cdn [cdn-name]')
30
- .description('Scaffold the CDN / Registry backend')
31
- .action(async (name) => {
32
- await createCdnCommand(name);
33
- process.exit(0);
34
- });
35
-
36
- // --- COMMAND: esad host ---
37
- program
38
- .command('host <subcommand>')
39
- .description('Manage the Host App (dev, android, ios)')
40
- .action(async (sub) => {
41
- await hostCommand(sub);
42
- process.exit(0);
43
- });
44
-
45
- // --- COMMAND: esad create-module ---
46
- program
47
- .command('create-module <module-name>')
48
- .description('Scaffold a React Native mini-app automatically configured for Module Federation via ESAD')
49
- .action(async (name) => {
50
- await createModuleCommand(name);
51
- process.exit(0);
52
- });
53
-
54
- // --- COMMAND: esad deploy ---
55
- program
56
- .command('deploy')
57
- .option('-v, --version <semver>', 'Version number (e.g., 1.0.0)')
58
- .option('-i, --id <moduleId>', 'The Module ID to deploy')
59
- .option('-e, --entry <entryFileName>', 'The name of the main entry bundle (e.g., index.bundle)', 'index.bundle')
60
- .description('Zips the local dist directory and uploads it to the configured deployment endpoint')
61
- .action(async (options) => {
62
- await deployCommand(options);
63
- process.exit(0);
64
- });
65
-
66
- // --- COMMAND: esad dev ---
67
- program
68
- .command('dev')
69
- .option('-i, --id <moduleId>', 'The Module ID to run in dev mode')
70
- .option('-p, --port <port>', 'The port to run the dev server on', '8081')
71
- .description('Starts the dev server and updates the external registry to bypass CDN')
72
- .action(async (options) => {
73
- await devCommand(options);
74
- // Note: dev command has its own shutdown logic with SIGINT/SIGTERM
75
- });
76
-
77
- program.parse(process.argv);
2
+
3
+ const { program } = require('commander');
4
+ const pkg = require('../package.json');
5
+
6
+ // Import Commands
7
+ const initCommand = require('../src/cli/commands/init');
8
+ const createModuleCommand = require('../src/cli/commands/createModule');
9
+ const createCdnCommand = require('../src/cli/commands/createCdn');
10
+ const deployCommand = require('../src/cli/commands/deploy');
11
+ const devCommand = require('../src/cli/commands/dev');
12
+ const hostCommand = require('../src/cli/commands/host');
13
+ const buildCommand = require('../src/cli/commands/build');
14
+
15
+ program
16
+ .version(pkg.version)
17
+ .description('esad - Easy Super App Development Toolkit');
18
+
19
+ // --- COMMMAND: esad init ---
20
+ program
21
+ .command('init <project-name>')
22
+ .description('Scaffold a new ESAD workspace containing the Host App')
23
+ .action(async (name) => {
24
+ await initCommand(name);
25
+ process.exit(0);
26
+ });
27
+
28
+ // --- COMMAND: esad create-cdn ---
29
+ program
30
+ .command('create-cdn [cdn-name]')
31
+ .description('Scaffold the CDN / Registry backend')
32
+ .action(async (name) => {
33
+ await createCdnCommand(name);
34
+ process.exit(0);
35
+ });
36
+
37
+ // --- COMMAND: esad host ---
38
+ program
39
+ .command('host <subcommand>')
40
+ .description('Manage the Host App (dev, android, ios)')
41
+ .action(async (sub) => {
42
+ await hostCommand(sub);
43
+ process.exit(0);
44
+ });
45
+
46
+ // --- COMMAND: esad create-module ---
47
+ program
48
+ .command('create-module <module-name>')
49
+ .description('Scaffold a React Native mini-app automatically configured for Module Federation via ESAD')
50
+ .action(async (name) => {
51
+ await createModuleCommand(name);
52
+ process.exit(0);
53
+ });
54
+
55
+ // --- COMMAND: esad build ---
56
+ program
57
+ .command('build')
58
+ .option('-i, --id <moduleId>', 'The Module ID to build')
59
+ .option('-p, --platform <platform>', 'Platform to build for (android, ios)', 'android')
60
+ .description('Builds a production bundle for the host or a specific module')
61
+ .action(async (options) => {
62
+ await buildCommand(options);
63
+ process.exit(0);
64
+ });
65
+
66
+ // --- COMMAND: esad deploy ---
67
+ program
68
+ .command('deploy')
69
+ .option('-v, --version <semver>', 'Version number (e.g., 1.0.0)')
70
+ .option('-i, --id <moduleId>', 'The Module ID to deploy')
71
+ .option('-e, --entry <entryFileName>', 'The name of the main entry bundle (e.g., index.bundle)', 'index.bundle')
72
+ .description('Zips the local dist directory and uploads it to the configured deployment endpoint')
73
+ .action(async (options) => {
74
+ await deployCommand(options);
75
+ process.exit(0);
76
+ });
77
+
78
+ // --- COMMAND: esad dev ---
79
+ program
80
+ .command('dev')
81
+ .option('-i, --id <moduleId>', 'The Module ID to run in dev mode')
82
+ .option('-p, --port <port>', 'The port to run the dev server on', '8081')
83
+ .description('Starts the dev server and updates the external registry to bypass CDN')
84
+ .action(async (options) => {
85
+ await devCommand(options);
86
+ // Note: dev command has its own shutdown logic with SIGINT/SIGTERM
87
+ });
88
+
89
+ program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemoreira/esad",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "Easy Super App Development - Zero-Config CLI and DevTools for React Native Module Federation",
5
5
  "main": "src/plugin/index.js",
6
6
  "types": "./src/plugin/index.d.ts",
@@ -34,7 +34,9 @@
34
34
  "chalk": "^4.1.2",
35
35
  "commander": "^11.1.0",
36
36
  "cross-spawn": "^7.0.3",
37
- "fs-extra": "^11.2.0"
37
+ "form-data": "^4.0.0",
38
+ "fs-extra": "^11.2.0",
39
+ "node-fetch": "^2.7.0"
38
40
  },
39
41
  "devDependencies": {
40
42
  "@rspack/core": "^1.7.9",
@@ -0,0 +1,53 @@
1
+ const { runProcess } = require('../utils/process');
2
+ const path = require('path');
3
+ const fs = require('fs-extra');
4
+ const chalk = require('chalk');
5
+ const { getWorkspaceConfig } = require('../utils/config');
6
+ const { resolveProjectDir, listAvailableModules } = require('../utils/resolution');
7
+
8
+ module.exports = async (options) => {
9
+ let cwd = process.cwd();
10
+
11
+ // Enforce Workspace Root
12
+ const configObj = getWorkspaceConfig();
13
+ if (!configObj) {
14
+ console.error(chalk.red(`❌ Error: Call this command from the project root (esad.config.json not found).`));
15
+ process.exit(1);
16
+ }
17
+
18
+ const { projectName } = configObj.data;
19
+
20
+ if (options.id) {
21
+ const targetDir = resolveProjectDir(options.id, configObj);
22
+ if (!targetDir) {
23
+ console.error(chalk.red(`\n❌ Error: Module not found: ${options.id}`));
24
+ listAvailableModules(configObj);
25
+ process.exit(1);
26
+ }
27
+ cwd = targetDir;
28
+ } else {
29
+ // Build host by default if in root
30
+ const hostDir = path.join(path.dirname(configObj.path), `${projectName}-host`);
31
+ if (fs.existsSync(hostDir)) cwd = hostDir;
32
+ }
33
+
34
+ const platform = options.platform || 'android';
35
+
36
+ console.log(`\n🏗️ Building production bundle for ${path.basename(cwd)} (${platform})...\n`);
37
+
38
+ try {
39
+ // Run Re.Pack production build
40
+ await runProcess('npx', [
41
+ 'react-native',
42
+ 'webpack-bundle',
43
+ '--platform', platform,
44
+ '--dev', 'false'
45
+ ], cwd);
46
+
47
+ console.log(chalk.green(`\n✅ Build complete! Assets generated in dist/ directory.`));
48
+ console.log(`👉 You can now run: esad deploy ${options.id ? `--id ${options.id}` : ''}\n`);
49
+ } catch (err) {
50
+ console.error(chalk.red(`\n❌ Build failed: ${err.message}`));
51
+ process.exit(1);
52
+ }
53
+ };
@@ -74,8 +74,36 @@ module.exports = async (options) => {
74
74
  console.log(`🗜️ Zipped output to ${zipPath}`);
75
75
 
76
76
  console.log(`🚀 Uploading to CDN via multipart POST...`);
77
- // Note: Here we would use form-data + fetch or axios to upload to Simple CDN
78
77
 
79
- console.log(`✅ [SIMULATED] Successfully uploaded to ${deployUrl}`);
80
- fs.unlinkSync(zipPath);
78
+ try {
79
+ const FormData = require('form-data'); // Standard in Node versions, or use native if available
80
+ const form = new FormData();
81
+ form.append('version', version);
82
+ form.append('bundle', fs.createReadStream(zipPath));
83
+
84
+ const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
85
+
86
+ // Simple CDN expects POST /api/admin/assets/:id/versions
87
+ const uploadUrl = deployUrl.includes('/versions') ? deployUrl : `${deployUrl}/versions`;
88
+
89
+ const response = await fetch(uploadUrl, {
90
+ method: 'POST',
91
+ body: form,
92
+ headers: form.getHeaders(),
93
+ });
94
+
95
+ if (response.ok) {
96
+ const result = await response.json();
97
+ console.log(chalk.green(`✅ Successfully uploaded ${moduleId} v${version} to CDN!`));
98
+ console.log(`📄 Active Version is now: ${result.active_version}`);
99
+ } else {
100
+ const errorText = await response.text();
101
+ console.error(chalk.red(`❌ Failed to upload: ${response.status} ${response.statusText}`));
102
+ console.error(errorText);
103
+ }
104
+ } catch (err) {
105
+ console.error(chalk.red(`❌ Error during upload: ${err.message}`));
106
+ } finally {
107
+ fs.unlinkSync(zipPath);
108
+ }
81
109
  };