@codemoreira/esad 2.0.1-0 ā 2.0.1-2
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 +11 -9
- package/package.json +3 -2
- package/src/cli/commands/build.js +1 -1
- package/src/cli/commands/create.js +4 -68
- package/src/cli/commands/init.js +75 -0
- package/src/cli/utils/config.js +1 -1
- package/src/cli/utils/process.js +55 -49
- package/src/cli/utils/transformer.js +4 -3
package/bin/esad.js
CHANGED
|
@@ -7,14 +7,21 @@ program
|
|
|
7
7
|
.version(pkg.version)
|
|
8
8
|
.description('esad - Easy Super App Development Toolkit (V2)');
|
|
9
9
|
|
|
10
|
-
// --- COMMAND: esad
|
|
10
|
+
// --- COMMAND: esad init [name] ---
|
|
11
|
+
program
|
|
12
|
+
.command('init [name]')
|
|
13
|
+
.description('Creates the base of an ESAD project (Workspace and Host App)')
|
|
14
|
+
.action(async (name) => {
|
|
15
|
+
await require('../src/cli/commands/init')(name);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// --- COMMAND: esad create [name] --type [module|cdn] ---
|
|
11
19
|
program
|
|
12
20
|
.command('create [name]')
|
|
13
|
-
.option('-t, --type <type>', 'Type of
|
|
14
|
-
.description('
|
|
21
|
+
.option('-t, --type <type>', 'Type of resource: module, cdn', 'module')
|
|
22
|
+
.description('Expands an existing workspace by scaffolding modules or a local cdn')
|
|
15
23
|
.action(async (name, options) => {
|
|
16
24
|
await require('../src/cli/commands/create')(name, options);
|
|
17
|
-
process.exit(0);
|
|
18
25
|
});
|
|
19
26
|
|
|
20
27
|
// --- COMMAND: esad dev [moduleId] ---
|
|
@@ -37,7 +44,6 @@ program
|
|
|
37
44
|
.action(async (id, options) => {
|
|
38
45
|
const opts = { ...options, id: id || options.id };
|
|
39
46
|
await require('../src/cli/commands/build')(opts);
|
|
40
|
-
process.exit(0);
|
|
41
47
|
});
|
|
42
48
|
|
|
43
49
|
// --- COMMAND: esad deploy [id] ---
|
|
@@ -49,7 +55,6 @@ program
|
|
|
49
55
|
.action(async (id, options) => {
|
|
50
56
|
const opts = { ...options, id: id || options.id };
|
|
51
57
|
await require('../src/cli/commands/deploy')(opts);
|
|
52
|
-
process.exit(0);
|
|
53
58
|
});
|
|
54
59
|
|
|
55
60
|
// --- COMMAND: esad host <sub> ---
|
|
@@ -58,7 +63,6 @@ program
|
|
|
58
63
|
.description('Manage host application (android, ios, login)')
|
|
59
64
|
.action(async (sub) => {
|
|
60
65
|
await require('../src/cli/commands/host')(sub);
|
|
61
|
-
process.exit(0);
|
|
62
66
|
});
|
|
63
67
|
|
|
64
68
|
// --- COMMAND: esad doctor ---
|
|
@@ -67,7 +71,6 @@ program
|
|
|
67
71
|
.description('Check environment for common issues')
|
|
68
72
|
.action(async () => {
|
|
69
73
|
await require('../src/cli/commands/doctor')();
|
|
70
|
-
process.exit(0);
|
|
71
74
|
});
|
|
72
75
|
|
|
73
76
|
// --- COMMAND: esad link [id] ---
|
|
@@ -76,7 +79,6 @@ program
|
|
|
76
79
|
.description('Optimize development via local filesystem linking')
|
|
77
80
|
.action(async (id) => {
|
|
78
81
|
await require('../src/cli/commands/link')(id);
|
|
79
|
-
process.exit(0);
|
|
80
82
|
});
|
|
81
83
|
|
|
82
84
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemoreira/esad",
|
|
3
|
-
"version": "2.0.1-
|
|
3
|
+
"version": "2.0.1-2",
|
|
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",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"cross-spawn": "^7.0.3",
|
|
51
51
|
"form-data": "^4.0.0",
|
|
52
52
|
"fs-extra": "^11.2.0",
|
|
53
|
+
"jiti": "^2.6.1",
|
|
53
54
|
"node-fetch": "^2.7.0",
|
|
54
55
|
"process": "^0.11.10"
|
|
55
56
|
},
|
|
@@ -58,4 +59,4 @@
|
|
|
58
59
|
"@types/react": "^19.2.14",
|
|
59
60
|
"@types/react-native": "^0.72.8"
|
|
60
61
|
}
|
|
61
|
-
}
|
|
62
|
+
}
|
|
@@ -38,7 +38,7 @@ module.exports = async (options) => {
|
|
|
38
38
|
syncContextDownwards(configObj);
|
|
39
39
|
|
|
40
40
|
try {
|
|
41
|
-
const bundleOutput = path.join(cwd, 'build', 'index.bundle');
|
|
41
|
+
const bundleOutput = path.join(cwd, 'build', platform, 'index.bundle');
|
|
42
42
|
fs.ensureDirSync(path.dirname(bundleOutput));
|
|
43
43
|
|
|
44
44
|
// Run Re.Pack production build
|
|
@@ -6,68 +6,6 @@ const { cloneTemplate, renameProject } = require('../utils/scaffold');
|
|
|
6
6
|
const { getWorkspaceConfig } = require('../utils/config');
|
|
7
7
|
const templatesConfig = require('../templates/templates.json');
|
|
8
8
|
|
|
9
|
-
const initHost = async (projectName) => {
|
|
10
|
-
const workspaceDir = path.join(process.cwd(), projectName);
|
|
11
|
-
console.log(`\nš Initializing ESAD Workspace: ${projectName}...\n`);
|
|
12
|
-
|
|
13
|
-
fs.ensureDirSync(workspaceDir);
|
|
14
|
-
|
|
15
|
-
const configPath = path.join(workspaceDir, 'esad.config.js');
|
|
16
|
-
if (!fs.existsSync(configPath)) {
|
|
17
|
-
const configTemplate = `/**
|
|
18
|
-
* ESAD: Super App Configuration
|
|
19
|
-
*/
|
|
20
|
-
export default {
|
|
21
|
-
projectName: '${projectName}',
|
|
22
|
-
|
|
23
|
-
// 1. Development Overrides
|
|
24
|
-
// Managed automatically by 'esad dev'
|
|
25
|
-
devMode: {},
|
|
26
|
-
|
|
27
|
-
// 2. Programmable Deployment
|
|
28
|
-
// Receives the compiled bundle.
|
|
29
|
-
async deploy(bundle, { version, moduleId, options }) {
|
|
30
|
-
console.log('š Starting custom upload for ' + moduleId + '...');
|
|
31
|
-
// return { status: 'mock_success', moduleId, version };
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
`;
|
|
35
|
-
fs.writeFileSync(configPath, configTemplate);
|
|
36
|
-
console.log(`ā
Generated programmable configuration: esad.config.js`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const gitignorePath = path.join(workspaceDir, '.gitignore');
|
|
40
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
41
|
-
const hostName = `${projectName}-host`;
|
|
42
|
-
const gitignoreContent = `# ESAD Workspace Git Configuration\n` +
|
|
43
|
-
`/*\n\n` +
|
|
44
|
-
`!/${hostName}/\n` +
|
|
45
|
-
`!/esad.config.js\n` +
|
|
46
|
-
`!/.gitignore\n` +
|
|
47
|
-
`\nnode_modules/\n`;
|
|
48
|
-
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
49
|
-
console.log(`ā
Generated .gitignore`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const hostName = `${projectName}-host`;
|
|
53
|
-
const hostDir = path.join(workspaceDir, hostName);
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
await cloneTemplate(templatesConfig.host, hostDir);
|
|
57
|
-
await renameProject(hostDir, hostName);
|
|
58
|
-
|
|
59
|
-
// Inject local context mock immediately to avoid crashes on fresh boot
|
|
60
|
-
fs.writeJsonSync(path.join(hostDir, '.esad.context.json'), { projectName, devMode: {} }, { spaces: 2 });
|
|
61
|
-
|
|
62
|
-
console.log(`\nš¦ Installing dependencies into host...`);
|
|
63
|
-
await runProcess('npm', ['install'], { cwd: hostDir });
|
|
64
|
-
console.log(`\nš ESAD Workspace Initialized!`);
|
|
65
|
-
console.log(`-> cd ${projectName}/${hostName}\n-> esad host dev (to start Host)`);
|
|
66
|
-
} catch (err) {
|
|
67
|
-
console.error(`ā Failed to init Host:`, err.message);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
9
|
const createModule = async (moduleName) => {
|
|
72
10
|
const configObj = getWorkspaceConfig();
|
|
73
11
|
if (!configObj) {
|
|
@@ -138,11 +76,9 @@ module.exports = async (name, options) => {
|
|
|
138
76
|
const type = options.type;
|
|
139
77
|
|
|
140
78
|
if (type === 'host') {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
return await initHost(name);
|
|
79
|
+
console.error(chalk.red('ā Error: The "host" type is no longer supported in create.'));
|
|
80
|
+
console.error(chalk.yellow('š Use "esad init <project-name>" instead to create a new workspace.'));
|
|
81
|
+
process.exit(1);
|
|
146
82
|
}
|
|
147
83
|
|
|
148
84
|
if (type === 'module') {
|
|
@@ -157,5 +93,5 @@ module.exports = async (name, options) => {
|
|
|
157
93
|
return await createCdn(name);
|
|
158
94
|
}
|
|
159
95
|
|
|
160
|
-
console.error(chalk.red(`ā Unknown type: ${type}. Valid types are:
|
|
96
|
+
console.error(chalk.red(`ā Unknown type: ${type}. Valid types are: module, cdn.`));
|
|
161
97
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { runProcess } = require('../utils/process');
|
|
5
|
+
const { cloneTemplate, renameProject } = require('../utils/scaffold');
|
|
6
|
+
const templatesConfig = require('../templates/templates.json');
|
|
7
|
+
|
|
8
|
+
module.exports = async (projectName) => {
|
|
9
|
+
if (!projectName) {
|
|
10
|
+
console.error(chalk.red('ā Error: Project name is required to initialize a new ESAD workspace.'));
|
|
11
|
+
console.error(chalk.yellow('š Usage: esad init <project-name>'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const workspaceDir = path.join(process.cwd(), projectName);
|
|
16
|
+
console.log(`\nš Initializing ESAD Workspace: ${projectName}...\n`);
|
|
17
|
+
|
|
18
|
+
fs.ensureDirSync(workspaceDir);
|
|
19
|
+
|
|
20
|
+
const configPath = path.join(workspaceDir, 'esad.config.js');
|
|
21
|
+
if (!fs.existsSync(configPath)) {
|
|
22
|
+
const configTemplate = `/**
|
|
23
|
+
* ESAD: Super App Configuration
|
|
24
|
+
*/
|
|
25
|
+
export default {
|
|
26
|
+
projectName: '${projectName}',
|
|
27
|
+
|
|
28
|
+
// 1. Development Overrides
|
|
29
|
+
// Managed automatically by 'esad dev'
|
|
30
|
+
devMode: {},
|
|
31
|
+
|
|
32
|
+
// 2. Programmable Deployment
|
|
33
|
+
// Receives the compiled bundle.
|
|
34
|
+
async deploy(bundle, { version, moduleId, options }) {
|
|
35
|
+
console.log('š Starting custom upload for ' + moduleId + '...');
|
|
36
|
+
// return { status: 'mock_success', moduleId, version };
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
`;
|
|
40
|
+
fs.writeFileSync(configPath, configTemplate);
|
|
41
|
+
console.log(`ā
Generated programmable configuration: esad.config.js`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const gitignorePath = path.join(workspaceDir, '.gitignore');
|
|
45
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
46
|
+
const hostName = `${projectName}-host`;
|
|
47
|
+
const gitignoreContent = `# ESAD Workspace Git Configuration\n` +
|
|
48
|
+
`# Note: We use a whitelist approach because modules should be kept in separate repositories.\n` +
|
|
49
|
+
`/*\n\n` +
|
|
50
|
+
`!/${hostName}/\n` +
|
|
51
|
+
`!/esad.config.js\n` +
|
|
52
|
+
`!/.gitignore\n` +
|
|
53
|
+
`\nnode_modules/\n`;
|
|
54
|
+
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
55
|
+
console.log(`ā
Generated .gitignore`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const hostName = `${projectName}-host`;
|
|
59
|
+
const hostDir = path.join(workspaceDir, hostName);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await cloneTemplate(templatesConfig.host, hostDir);
|
|
63
|
+
await renameProject(hostDir, hostName);
|
|
64
|
+
|
|
65
|
+
// Inject local context mock immediately to avoid crashes on fresh boot
|
|
66
|
+
fs.writeJsonSync(path.join(hostDir, '.esad.context.json'), { projectName, devMode: {} }, { spaces: 2 });
|
|
67
|
+
|
|
68
|
+
console.log(`\nš¦ Installing dependencies into host...`);
|
|
69
|
+
await runProcess('npm', ['install'], { cwd: hostDir });
|
|
70
|
+
console.log(`\nš ESAD Workspace Initialized!`);
|
|
71
|
+
console.log(`-> cd ${projectName}/${hostName}\n-> esad host dev (to start Host)`);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error(`ā Failed to init Host:`, err.message);
|
|
74
|
+
}
|
|
75
|
+
};
|
package/src/cli/utils/config.js
CHANGED
|
@@ -20,7 +20,7 @@ const getWorkspaceConfig = () => {
|
|
|
20
20
|
|
|
21
21
|
try {
|
|
22
22
|
const jiti = createJiti(__filename);
|
|
23
|
-
const configModule = jiti
|
|
23
|
+
const configModule = jiti(configPath);
|
|
24
24
|
// jiti.import returns a promise for async imports if needed, but for esad.config.js
|
|
25
25
|
// we expect a sync structure or we resolve it.
|
|
26
26
|
// However, jiti v2 import is async.
|
package/src/cli/utils/process.js
CHANGED
|
@@ -4,63 +4,69 @@ const path = require('path');
|
|
|
4
4
|
const fs = require('fs-extra');
|
|
5
5
|
|
|
6
6
|
const runProcess = (cmd, args, cwd = process.cwd()) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let childRef;
|
|
8
|
+
const promise = new Promise((resolve, reject) => {
|
|
9
|
+
let finished = false;
|
|
10
|
+
let started = false;
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const finalize = (fn, arg) => {
|
|
13
|
+
if (finished) return;
|
|
14
|
+
finished = true;
|
|
15
|
+
fn(arg);
|
|
16
|
+
};
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const isWin = process.platform === 'win32';
|
|
19
|
+
const localBin = isWin ? `${cmd}.cmd` : cmd;
|
|
20
|
+
const localBinPath = path.join(cwd, 'node_modules', '.bin', localBin);
|
|
21
|
+
|
|
22
|
+
let command = cmd;
|
|
23
|
+
let finalArgs = args;
|
|
24
|
+
let useNativeSpawn = false;
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
if (fs.existsSync(localBinPath)) {
|
|
27
|
+
// 1. Priority: Local node_modules/.bin (fastest & consistent)
|
|
28
|
+
command = isWin ? `node_modules\\.bin\\${localBin}` : `./node_modules/.bin/${localBin}`;
|
|
29
|
+
useNativeSpawn = isWin;
|
|
30
|
+
} else {
|
|
31
|
+
// 2. Fallback: System Path (git, npm, npx, etc)
|
|
32
|
+
// cross-spawn handles .cmd/.exe resolution automatically
|
|
33
|
+
command = cmd;
|
|
34
|
+
finalArgs = args;
|
|
35
|
+
useNativeSpawn = false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log(`[ESAD] Resolved Command: ${command} (CWD: ${cwd})`);
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
setTimeout(() => { started = true; }, 2000);
|
|
40
|
+
setTimeout(() => { started = true; }, 2000);
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
const spawnFn = useNativeSpawn ? nativeSpawn : spawn;
|
|
43
|
+
childRef = spawnFn(command, finalArgs, {
|
|
44
|
+
stdio: 'inherit',
|
|
45
|
+
cwd,
|
|
46
|
+
shell: true
|
|
47
|
+
});
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
49
|
+
childRef.on('error', err => {
|
|
50
|
+
if (started && err.code === 'ENOENT') {
|
|
51
|
+
console.warn(`[ESAD] Warning: Late ENOENT ignored for ${cmd}.`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
finalize(reject, err);
|
|
55
|
+
});
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
childRef.on('close', code => {
|
|
58
|
+
if (code !== 0) {
|
|
59
|
+
finalize(reject, new Error(`Process ${cmd} exited with code ${code}`));
|
|
60
|
+
} else {
|
|
61
|
+
finalize(resolve);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
54
64
|
});
|
|
55
65
|
|
|
56
|
-
child
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
};
|
|
66
|
+
promise.child = childRef;
|
|
67
|
+
promise.kill = (signal) => childRef && childRef.kill(signal);
|
|
68
|
+
|
|
69
|
+
return promise;
|
|
70
|
+
};
|
|
65
71
|
|
|
66
72
|
module.exports = { runProcess };
|
|
@@ -51,13 +51,14 @@ const clearAllDevMode = (configPath) => {
|
|
|
51
51
|
fs.writeFileSync(configPath, content);
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
const { createJiti } = require('jiti');
|
|
55
|
+
|
|
54
56
|
const syncContextDownwards = (configObj) => {
|
|
55
57
|
if (!fs.existsSync(configObj.path)) return;
|
|
56
58
|
const configDir = path.dirname(configObj.path);
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let configContent = require(configObj.path);
|
|
60
|
+
const jiti = createJiti(__filename);
|
|
61
|
+
let configContent = jiti(configObj.path);
|
|
61
62
|
if (configContent.default) configContent = configContent.default;
|
|
62
63
|
|
|
63
64
|
const exportData = {
|