@codemoreira/esad 1.4.6-9 โ†’ 2.0.0-rc.1

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/README.md CHANGED
@@ -1,96 +1,82 @@
1
- # ESAD (Easy Super App Development) ๐Ÿš€
2
-
3
- Zero-Config CLI and DevTools for React Native Module Federation + Expo.
4
-
5
- ESAD is a unified toolkit designed to abstract all the complexity from Super App development using **Re.Pack (Rspack)** and **Expo**.
6
-
7
- ---
8
-
9
- ## ๐Ÿ—๏ธ CLI Commands
10
-
11
- ### 1. Initialize a Workspace
12
- ```bash
13
- npx @codemoreira/esad init my-project
14
- ```
15
-
16
- ### 2. Create a Federated Module
17
- ```bash
18
- npx esad create-module module-name
19
- ```
20
-
21
- ### 3. Create a Local CDN / Registry
22
- ```bash
23
- npx esad create-cdn
24
- ```
25
-
26
- ### 4. Development & Cloud-Sync
27
- Starts the Rspack server locally OR performs a **Dev-Cloud Sync** for remote preview.
28
- ```bash
29
- npx esad dev --id module-name # Builds and pushes bundle to Dev Cloud
30
- ```
31
-
32
- ### 5. Host Automation
33
- Manages the Host App and automatically synchronizes project-wide configurations (Auto-Sync).
34
- ```bash
35
- npx esad host android # Run Host on Android
36
- ```
37
-
38
- ### 5. Build for Production
39
- Prepares the bundle and chunks for deployment, generating a standardized `./build` directory.
40
- ```bash
41
- npx esad build --id module-name --platform android
42
- ```
43
-
44
- ### 6. Deployment
45
- Packages the `./build` folder and uploads it to your configured Registry/CDN via multipart POST.
46
- ```bash
47
- npx esad deploy --id module-name --version 1.0.0
48
- ```
49
-
50
- ---
51
-
52
- ## ๐Ÿ› ๏ธ Library Usage
53
-
54
- ### ๐ŸŽจ Bundler Plugin (`@codemoreira/esad/plugin`)
55
- Wrap your configuration to enable ESAD's smart resolution and redirection logic:
56
- ```javascript
57
- import { withESAD } from '@codemoreira/esad/plugin';
58
-
59
- export default withESAD({
60
- type: 'module', // or 'host'
61
- id: 'my-mini-app'
62
- });
63
- ```
64
-
65
- ### โšก Global State SDK (`@codemoreira/esad/client`)
66
- Share state across the Host and all Remote Modules reactively via a **Universal Singleton**:
67
- ```javascript
68
- import { useESADState } from '@codemoreira/esad/client';
69
-
70
- const [user, setUser] = useESADState('user');
71
- ```
72
-
73
- ---
74
-
75
- ## โš™๏ธ Configuration (`esad.config.json`)
76
-
77
- ESAD supports a "Zero-Config" but powerful orchestration file at the root:
78
- - `projectName`: Your SuperApp identifier.
79
- - `devModeFor`: Array of **shorthand** module names (e.g. `["recebimento"]`) to load from the Dev Cloud instead of Production.
80
- - **Auto-Sync**: CLI commands (`dev`, `build`, `deploy`) automatically propagate this config to the Host App.
81
-
82
- ---
83
-
84
- ## ๐Ÿ  Template Features (Host & Module)
85
-
86
- ESAD provides high-quality, boilerplate-free templates:
87
- - **๐Ÿš€ Rspack + Re.Pack**: Blazing fast builds powered by Rspack.
88
- - **๐Ÿ“ฑ Clean UI**: Modern, responsive designs built with **Vanilla StyleSheet** (No external CSS libraries required).
89
- - **๐Ÿ›ค๏ธ Dynamic Navigation**: Pre-configured Dashboard and Module Viewer with **Suspense** support.
90
- - **๐Ÿ” State-Driven Auth**: Built-in login and session management via the ESAD SDK.
91
- - **๐Ÿ”ง Automated Patching**: CLI-driven injection of Re.Pack extensions into Android and iOS native projects.
92
-
93
- ---
94
-
95
- ## ๐ŸŽจ Architecture & Workflow
96
- For technical diagrams and the modular deployment lifecycle, see [ESAD_ARCHITECTURE.md](./ESAD_ARCHITECTURE.md).
1
+ # ESAD (Easy Super App Development) ๐Ÿš€
2
+
3
+ Zero-Config CLI and DevTools for React Native Module Federation + Expo.
4
+
5
+ ESAD is a unified toolkit designed to abstract all the complexity from Super App development using **Re.Pack (Rspack)** and **Expo**.
6
+
7
+ ---
8
+
9
+ ## ๐Ÿ—๏ธ CLI Commands
10
+
11
+ ### 1. Initialize a Workspace
12
+ ```bash
13
+ npx @codemoreira/esad init my-project
14
+ ```
15
+
16
+ ### 2. Create a Federated Module
17
+ ```bash
18
+ npx esad create-module module-name
19
+ ```
20
+
21
+ ### 3. Create a Local CDN / Registry
22
+ ```bash
23
+ npx esad create-cdn
24
+ ```
25
+
26
+ ### 4. Development & Native Automation
27
+ Starts the Rspack server and **automatically patches** native files (Gradle, Entry Points) if necessary.
28
+ ```bash
29
+ npx esad host dev # Run the Host App
30
+ npx esad dev --id module-name --port 9000 # Run a Module
31
+ ```
32
+
33
+ ### 5. Build for Production
34
+ Prepares the bundle and chunks for deployment, generating a standardized `./build` directory.
35
+ ```bash
36
+ npx esad build --id module-name --platform android
37
+ ```
38
+
39
+ ### 6. Deployment
40
+ Packages the `./build` folder and uploads it to your configured Registry/CDN via multipart POST.
41
+ ```bash
42
+ npx esad deploy --id module-name --version 1.0.0
43
+ ```
44
+
45
+ ---
46
+
47
+ ## ๐Ÿ› ๏ธ Library Usage
48
+
49
+ ### ๐ŸŽจ Bundler Plugin (`@codemoreira/esad/plugin`)
50
+ Wrap your configuration to enable ESAD's smart resolution and redirection logic:
51
+ ```javascript
52
+ import { withESAD } from '@codemoreira/esad/plugin';
53
+
54
+ export default withESAD({
55
+ type: 'module', // or 'host'
56
+ id: 'my-mini-app'
57
+ });
58
+ ```
59
+
60
+ ### โšก Global State SDK (`@codemoreira/esad/client`)
61
+ Share state across the Host and all Remote Modules reactively:
62
+ ```javascript
63
+ import { useESADState } from '@codemoreira/esad/client';
64
+
65
+ const [user, setUser] = useESADState('user');
66
+ ```
67
+
68
+ ---
69
+
70
+ ## ๐Ÿ  Template Features (Host & Module)
71
+
72
+ ESAD provides high-quality, boilerplate-free templates:
73
+ - **๐Ÿš€ Rspack + Re.Pack**: Blazing fast builds powered by Rspack.
74
+ - **๐Ÿ“ฑ Clean UI**: Modern, responsive designs built with **Vanilla StyleSheet** (No external CSS libraries required).
75
+ - **๐Ÿ›ค๏ธ Dynamic Navigation**: Pre-configured Dashboard and Module Viewer with **Suspense** support.
76
+ - **๐Ÿ” State-Driven Auth**: Built-in login and session management via the ESAD SDK.
77
+ - **๐Ÿ”ง Automated Patching**: CLI-driven injection of Re.Pack extensions into Android and iOS native projects.
78
+
79
+ ---
80
+
81
+ ## ๐ŸŽจ Architecture & Workflow
82
+ For technical diagrams and the modular deployment lifecycle, see [ESAD_ARCHITECTURE.md](./ESAD_ARCHITECTURE.md).
package/bin/esad.js CHANGED
@@ -1,115 +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
- const buildCommand = require('../src/cli/commands/build');
14
-
15
- program
16
- .version(pkg.version)
17
- .description('esad - Easy Super App Development Toolkit');
18
-
19
- // --- COMMAND: 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')
31
- .description('Scaffold the CDN backend (always named {{projectName}}-cdn)')
32
- .action(async (name) => {
33
- await createCdnCommand(name);
34
- process.exit(0);
35
- });
36
-
37
- // --- COMMAND: esad dev ---
38
- program
39
- .command('dev [platform]')
40
- .description('Start the development environment for the Host App (platform: android, ios)')
41
- .action(async (platform) => {
42
- await hostCommand(platform);
43
- process.exit(0);
44
- });
45
-
46
- // --- COMMAND: esad android ---
47
- program
48
- .command('android')
49
- .description('Run Host on Android (alias for esad dev android)')
50
- .action(async () => {
51
- await hostCommand('android');
52
- process.exit(0);
53
- });
54
-
55
- // --- COMMAND: esad ios ---
56
- program
57
- .command('ios')
58
- .description('Run Host on iOS (alias for esad dev ios)')
59
- .action(async () => {
60
- await hostCommand('ios');
61
- process.exit(0);
62
- });
63
-
64
- // --- COMMAND: esad start ---
65
- program
66
- .command('start')
67
- .description('Alias for esad dev')
68
- .action(async () => {
69
- await hostCommand('dev');
70
- process.exit(0);
71
- });
72
-
73
- // --- COMMAND: esad push ---
74
- program
75
- .command('push')
76
- .option('-i, --id <moduleId>', 'The Module ID to sync to Dev-Cloud')
77
- .option('-p, --platform <platform>', 'Platform (android, ios)', 'android')
78
- .description('Build and Push the module bundle to the Dev-Cloud for global previewing')
79
- .action(async (options) => {
80
- await devCommand(options);
81
- });
82
-
83
- // --- COMMAND: esad create-module ---
84
- program
85
- .command('create-module <module-name>')
86
- .description('Scaffold a React Native mini-app automatically configured for Module Federation via ESAD')
87
- .action(async (name) => {
88
- await createModuleCommand(name);
89
- process.exit(0);
90
- });
91
-
92
- // --- COMMAND: esad build ---
93
- program
94
- .command('build')
95
- .option('-i, --id <moduleId>', 'The Module ID to build')
96
- .option('-p, --platform <platform>', 'Platform to build for (android, ios)', 'android')
97
- .description('Builds a production bundle for the host or a specific module')
98
- .action(async (options) => {
99
- await buildCommand(options);
100
- process.exit(0);
101
- });
102
-
103
- // --- COMMAND: esad deploy ---
104
- program
105
- .command('deploy')
106
- .option('-v, --version <semver>', 'Version number (e.g., 1.0.0)')
107
- .option('-i, --id <moduleId>', 'The Module ID to deploy')
108
- .option('-e, --entry <entryFileName>', 'The name of the main entry bundle (e.g., index.bundle)', 'index.bundle')
109
- .description('Zips the local dist directory and uploads it to the configured deployment endpoint')
110
- .action(async (options) => {
111
- await deployCommand(options);
112
- process.exit(0);
113
- });
114
-
115
- 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.4.6-9",
3
+ "version": "2.0.0-rc.1",
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",
@@ -16,8 +16,7 @@
16
16
  "./client": {
17
17
  "types": "./src/client/index.d.ts",
18
18
  "default": "./src/client/index.js"
19
- },
20
- "./config-plugin": "./src/plugin/config-plugin.js"
19
+ }
21
20
  },
22
21
  "bin": {
23
22
  "esad": "./bin/esad.js"
@@ -30,28 +29,29 @@
30
29
  "scripts": {
31
30
  "test": "echo \"Error: no test specified\" && exit 1"
32
31
  },
32
+ "overrides": {
33
+ "axios": "1.15.0",
34
+ "@xmldom/xmldom": "0.9.9"
35
+ },
33
36
  "dependencies": {
37
+ "@babel/core": "^7.20.0",
34
38
  "@callstack/repack": "^5.2.5",
35
39
  "@callstack/repack-plugin-expo-modules": "^5.2.5",
36
40
  "@callstack/repack-plugin-reanimated": "^5.2.5",
37
- "@module-federation/enhanced": "^2.2.3",
41
+ "@module-federation/enhanced": "^2.3.1",
38
42
  "@rspack/core": "^1.7.8",
43
+ "@swc/core": "^1.7.0",
44
+ "@swc/helpers": "^0.5.11",
39
45
  "adm-zip": "^0.5.10",
46
+ "babel-loader": "^9.1.3",
47
+ "babel-preset-expo": "~12.0.0",
40
48
  "chalk": "^4.1.2",
41
49
  "commander": "^11.1.0",
42
50
  "cross-spawn": "^7.0.3",
43
- "@babel/core": "^7.20.0",
44
- "babel-loader": "^9.1.3",
45
- "babel-preset-expo": "~12.0.0",
46
- "expo": "~52.0.0",
47
- "react-native-reanimated": "~3.16.1",
48
51
  "form-data": "^4.0.0",
49
52
  "fs-extra": "^11.2.0",
50
53
  "node-fetch": "^2.7.0",
51
- "@babel/plugin-transform-flow-strip-types": "^7.20.0",
52
- "@babel/plugin-transform-private-methods": "^7.20.0",
53
- "@babel/plugin-transform-private-property-in-object": "^7.20.0",
54
- "@babel/plugin-transform-class-properties": "^7.20.0"
54
+ "process": "^0.11.10"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@rspack/core": "^1.7.9",
@@ -2,47 +2,42 @@ const { runProcess } = require('../utils/process');
2
2
  const path = require('path');
3
3
  const fs = require('fs-extra');
4
4
  const chalk = require('chalk');
5
- const { getWorkspaceConfig, syncHostConfig } = require('../utils/config');
6
- const { resolveProjectDir, listAvailableModules } = require('../utils/resolution');
7
- const { prepareNative } = require('../utils/scaffold');
5
+ const { getWorkspaceConfig } = require('../utils/config');
6
+ const { resolveProjectDir } = require('../utils/resolution');
7
+ const { clearAllDevMode } = require('../utils/transformer');
8
8
 
9
9
  module.exports = async (options) => {
10
- let cwd = process.cwd();
11
-
12
- // Enforce Workspace Root
13
10
  const configObj = getWorkspaceConfig();
14
11
  if (!configObj) {
15
- console.error(chalk.red(`โŒ Error: Call this command from the project root (esad.config.json not found).`));
12
+ console.error(chalk.red(`โŒ Error: esad.config.js not found.`));
16
13
  process.exit(1);
17
14
  }
18
15
 
19
- syncHostConfig(configObj);
20
-
21
- const { projectName } = configObj.data;
16
+ const config = await configObj.load();
17
+ const workspaceRoot = configObj.root;
18
+ const projectName = config.default?.projectName || config.projectName;
19
+
20
+ let cwd = process.cwd();
22
21
 
23
22
  if (options.id) {
24
23
  const targetDir = resolveProjectDir(options.id, configObj);
25
24
  if (!targetDir) {
26
- console.error(chalk.red(`\nโŒ Error: Module not found: ${options.id}`));
27
- listAvailableModules(configObj);
25
+ console.error(chalk.red(`โŒ Error: Module not found: ${options.id}`));
28
26
  process.exit(1);
29
27
  }
30
28
  cwd = targetDir;
31
- } else {
32
- // Build host by default if in root
33
- const hostDir = path.join(path.dirname(configObj.path), `${projectName}-host`);
34
- if (fs.existsSync(hostDir)) cwd = hostDir;
35
29
  }
36
30
 
37
31
  const platform = options.platform || 'android';
38
32
 
39
- // Prepare Native Folders
40
- await prepareNative(cwd, platform);
41
-
42
- console.log(`\n๐Ÿ—๏ธ Building production bundle for ${path.basename(cwd)} (${platform})...\n`);
33
+ console.log(`\n๐Ÿ—๏ธ Building production bundle for ${chalk.cyan(path.basename(cwd))} (${platform})...\n`);
43
34
 
35
+ // 1. CLEANUP CONFIG (Avoid shipping local dev URLs)
36
+ console.log(chalk.gray(`๐Ÿงน Cleaning up devMode mappings in esad.config.js...`));
37
+ clearAllDevMode(configObj.path);
38
+
44
39
  try {
45
- const bundleOutput = path.join(cwd, 'build', platform, 'index.bundle');
40
+ const bundleOutput = path.join(cwd, 'build', 'index.bundle'); // Simplified path as per V2
46
41
  fs.ensureDirSync(path.dirname(bundleOutput));
47
42
 
48
43
  // Run Re.Pack production build
@@ -52,14 +47,14 @@ module.exports = async (options) => {
52
47
  '--platform', platform,
53
48
  '--dev', 'false',
54
49
  '--bundle-output', bundleOutput,
55
- '--assets-dest', path.dirname(bundleOutput),
56
- '--reset-cache'
57
- ], cwd);
50
+ '--assets-dest', path.dirname(bundleOutput)
51
+ ], { cwd });
58
52
 
59
53
  console.log(chalk.green(`\nโœ… Build complete! Assets generated in build/ directory.`));
60
- console.log(`๐Ÿ‘‰ You can now run: esad deploy ${options.id ? `--id ${options.id}` : ''}\n`);
54
+ console.log(`๐Ÿ‘‰ Next step: 'esad deploy ${options.id || ''}'\n`);
61
55
  } catch (err) {
62
56
  console.error(chalk.red(`\nโŒ Build failed: ${err.message}`));
63
57
  process.exit(1);
64
58
  }
65
59
  };
60
+
@@ -1,45 +1,44 @@
1
- const { runProcess } = require('../utils/process');
2
- const { getWorkspaceConfig } = require('../utils/config');
3
- const fs = require('fs-extra');
4
- const path = require('path');
5
-
6
- module.exports = async (cdnName) => {
7
- const configObj = getWorkspaceConfig();
8
- if (!configObj) {
9
- console.error(`โŒ Error: Call this command from inside an ESAD workspace (esad.config.json not found).`);
10
- return;
11
- }
12
-
13
- const { projectName } = configObj.data;
14
- const finalCdnName = `${projectName}-cdn`;
15
- const cdnPath = path.join(process.cwd(), finalCdnName);
16
-
17
- if (fs.existsSync(cdnPath)) {
18
- console.error(`โŒ Error: Directory ./${finalCdnName} already exists.`);
19
- return;
20
- }
21
-
22
- console.log(`\n๐Ÿ“ฆ Initializing Flux Registry & CDN: ${finalCdnName}...\n`);
23
-
24
- try {
25
- // 1. Clone the template
26
- console.log(`๐Ÿ“ก Cloning template from GitHub...`);
27
- await runProcess('git', ['clone', 'https://github.com/CodeMoreira/simple-cdn.git', finalCdnName]);
28
-
29
- // 2. Remove .git from template
30
- console.log(`๐Ÿงน Cleaning up template metadata...`);
31
- await fs.remove(path.join(cdnPath, '.git'));
32
-
33
- // 3. Install dependencies
34
- console.log(`\n๐Ÿ“ฅ Installing dependencies (this may take a minute)...`);
35
- await runProcess('npm', ['install'], cdnPath);
36
-
37
- console.log(`\nโœ… CDN Registry created successfully in ./${finalCdnName}\n`);
38
- console.log(`To start your CDN:`);
39
- console.log(` cd ${finalCdnName}`);
40
- console.log(` npm start\n`);
41
-
42
- } catch (error) {
43
- console.error(`\nโŒ Failed to create CDN: ${error.message}`);
44
- }
45
- };
1
+ const { runProcess } = require('../utils/process');
2
+ const { getWorkspaceConfig } = require('../utils/config');
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+
6
+ module.exports = async (cdnName) => {
7
+ const configObj = getWorkspaceConfig();
8
+ if (!configObj) {
9
+ console.error(`โŒ Error: Call this command from inside an ESAD workspace (esad.config.json not found).`);
10
+ return;
11
+ }
12
+
13
+ const finalCdnName = cdnName || `${configObj.data.projectName}-cdn`;
14
+ const cdnPath = path.join(process.cwd(), finalCdnName);
15
+
16
+ if (fs.existsSync(cdnPath)) {
17
+ console.error(`โŒ Error: Directory ./${finalCdnName} already exists.`);
18
+ return;
19
+ }
20
+
21
+ console.log(`\n๐Ÿ“ฆ Initializing Flux Registry & CDN: ${finalCdnName}...\n`);
22
+
23
+ try {
24
+ // 1. Clone the template
25
+ console.log(`๐Ÿ“ก Cloning template from GitHub...`);
26
+ await runProcess('git', ['clone', 'https://github.com/CodeMoreira/simple-cdn.git', finalCdnName]);
27
+
28
+ // 2. Remove .git from template
29
+ console.log(`๐Ÿงน Cleaning up template metadata...`);
30
+ await fs.remove(path.join(cdnPath, '.git'));
31
+
32
+ // 3. Install dependencies
33
+ console.log(`\n๐Ÿ“ฅ Installing dependencies (this may take a minute)...`);
34
+ await runProcess('npm', ['install'], cdnPath);
35
+
36
+ console.log(`\nโœ… CDN Registry created successfully in ./${finalCdnName}\n`);
37
+ console.log(`To start your CDN:`);
38
+ console.log(` cd ${finalCdnName}`);
39
+ console.log(` npm start\n`);
40
+
41
+ } catch (error) {
42
+ console.error(`\nโŒ Failed to create CDN: ${error.message}`);
43
+ }
44
+ };
@@ -8,12 +8,15 @@ const templatesConfig = require('../templates/templates.json');
8
8
  module.exports = async (moduleName) => {
9
9
  const configObj = getWorkspaceConfig();
10
10
  if (!configObj) {
11
- console.error(`โŒ Error: Call this command from inside an ESAD workspace (esad.config.json not found).`);
11
+ console.error(`โŒ Error: Call this command from inside an ESAD workspace (esad.config.js not found).`);
12
12
  return;
13
13
  }
14
14
 
15
- const { projectName } = configObj.data;
15
+ const config = await configObj.load();
16
+ const projectName = config.default?.projectName || config.projectName;
17
+
16
18
  const isPrefixed = moduleName.startsWith(`${projectName}-`);
19
+
17
20
  const finalModuleName = isPrefixed ? moduleName : `${projectName}-${moduleName}`;
18
21
 
19
22
  const workspaceDir = path.dirname(configObj.path);