@codemoreira/esad 2.0.1-29 β 2.0.1-30
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 +43 -43
- package/package.json +5 -5
- package/src/cli/utils/scaffold.js +26 -31
- package/src/plugin/index.js +83 -174
- package/src/plugin/withRepack.js +90 -0
- package/src/plugin/env-shim.js +0 -17
package/README.md
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
# ESAD
|
|
1
|
+
# ESAD: Easy Super App Development π
|
|
2
2
|
|
|
3
|
-
Zero-Config CLI
|
|
3
|
+
**Zero-Config CLI & Framework for React Native Module Federation + Expo.**
|
|
4
4
|
|
|
5
|
-
ESAD is a unified toolkit designed to abstract all the complexity
|
|
5
|
+
ESAD is a unified toolkit designed to abstract all the complexity of Super App development. It bridges **Expo SDK 52** and **Re.Pack 5 (Rspack)** into a professional, linear workflow.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## π₯ Key Features
|
|
10
|
+
|
|
11
|
+
- **β‘ Zero-Config Native**: Automatic Android/iOS patching via **Expo Config Plugins**. No more manual Gradle or Manifest edits.
|
|
12
|
+
- **π Rspack Powered**: Blazing fast bundle generation for both Host and Remote Modules.
|
|
13
|
+
- **π‘οΈ Authenticated Remotes**: Built-in support for **JWT-signed bundle resolution** and dynamic module discovery.
|
|
14
|
+
- **π¦ Shared Memory Bridge**: Reactive global state across federation boundaries using the ESAD Client SDK.
|
|
15
|
+
- **π§Ή Lifecycle Maestro**: Automated `prebuild`, script fixing, and dev-server management.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ποΈ Quick Start (V2)
|
|
10
20
|
|
|
11
21
|
### 1. Initialize a Workspace
|
|
12
22
|
Creates the project root, a programmable `esad.config.js`, and the Host Application.
|
|
13
23
|
```bash
|
|
14
|
-
npx @codemoreira/esad init my-
|
|
24
|
+
npx @codemoreira/esad init my-super-app
|
|
15
25
|
```
|
|
16
26
|
|
|
17
27
|
### 2. Expand your Workspace
|
|
18
|
-
Create new Federated Modules
|
|
28
|
+
Create new Federated Modules with built-in navigation and shared state examples.
|
|
19
29
|
```bash
|
|
20
|
-
esad create my-
|
|
21
|
-
esad create --type cdn # Scaffolds a local registry for testing
|
|
30
|
+
esad create my-feature --type module
|
|
22
31
|
```
|
|
23
32
|
|
|
24
|
-
### 3. Development Manager (
|
|
25
|
-
The `dev` command
|
|
33
|
+
### 3. Development Manager (The Maestro)
|
|
34
|
+
The `dev` command handles everything: Prebuilds, Script Fixing, and Native Launch.
|
|
26
35
|
|
|
27
|
-
**Run the Host App
|
|
36
|
+
**Run the Host App:**
|
|
28
37
|
```bash
|
|
29
38
|
esad dev
|
|
30
39
|
```
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
**Run a specific Module:**
|
|
34
|
-
```bash
|
|
35
|
-
esad dev my-module --port 9000
|
|
36
|
-
```
|
|
37
|
-
*Starts the module server and updates the Host's local mapping automatically.*
|
|
40
|
+
*Choose Android or iOS. The CLI will automatically run `expo prebuild` if native folders are missing.*
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
Prepare and push your features to the registry.
|
|
41
|
-
|
|
42
|
-
**Build for Production:**
|
|
43
|
-
```bash
|
|
44
|
-
esad build my-module --platform android
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Execute Programmable Deploy:**
|
|
42
|
+
**Run a specific Module (in a separate terminal):**
|
|
48
43
|
```bash
|
|
49
|
-
esad
|
|
44
|
+
esad dev my-feature --port 9000
|
|
50
45
|
```
|
|
51
46
|
|
|
52
47
|
---
|
|
53
48
|
|
|
54
|
-
## π οΈ
|
|
49
|
+
## π οΈ Toolset Usage
|
|
55
50
|
|
|
56
51
|
### π¨ Bundler Plugin (`@codemoreira/esad/plugin`)
|
|
57
|
-
|
|
52
|
+
The `withESAD` wrapper automates Module Federation v2 setup and dynamic exposes:
|
|
58
53
|
```javascript
|
|
59
54
|
import { withESAD } from '@codemoreira/esad/plugin';
|
|
60
55
|
|
|
61
|
-
export default withESAD({
|
|
62
|
-
type: 'module',
|
|
63
|
-
id: 'my-
|
|
56
|
+
export default withESAD(env, {
|
|
57
|
+
type: 'module',
|
|
58
|
+
id: 'my-feature',
|
|
59
|
+
dirname: __dirname
|
|
64
60
|
});
|
|
65
61
|
```
|
|
66
62
|
|
|
67
|
-
### β‘
|
|
63
|
+
### β‘ Client SDK (`@codemoreira/esad/client`)
|
|
68
64
|
Share state across the Host and all Remote Modules reactively:
|
|
69
65
|
```javascript
|
|
70
66
|
import { useESADState } from '@codemoreira/esad/client';
|
|
71
67
|
|
|
72
|
-
const [user, setUser] = useESADState('
|
|
68
|
+
const [user, setUser] = useESADState('auth_user');
|
|
69
|
+
const [counter, setCounter] = useESADState('global_counter', 0);
|
|
73
70
|
```
|
|
74
71
|
|
|
75
72
|
---
|
|
76
73
|
|
|
77
|
-
##
|
|
74
|
+
## ποΈ Architecture & Deep Dive
|
|
75
|
+
For technical diagrams, lifecycle details, and the "Zero-Config" philosophy, see [ESAD_ARCHITECTURE.md](./ESAD_ARCHITECTURE.md).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## π Modern Templates
|
|
78
80
|
ESAD templates provide a high-end starting point:
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
- **π State-Driven Auth**: Built-in login and session management via the ESAD SDK.
|
|
83
|
-
- **π§ Automated Native Patching**: Zero-config injection into Android/iOS projects.
|
|
81
|
+
- **Navigation Multi-pΓ‘gina**: Federated modules with internal stack navigators.
|
|
82
|
+
- **Real Auth**: Integration-ready for Simple-CDN registries via JWT.
|
|
83
|
+
- **Smart UI**: Pre-configured Skeletons, Typography, and Modern Dark Mode.
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
> [!TIP]
|
|
88
|
+
> **Why ESAD?** React Native Module Federation is hard. ESAD makes it as easy as a standard Expo app while keeping the power of dynamic micro-frontends.
|
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-30",
|
|
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,6 +16,9 @@
|
|
|
16
16
|
"./client": {
|
|
17
17
|
"types": "./src/client/index.d.ts",
|
|
18
18
|
"default": "./src/client/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./expo-plugin": {
|
|
21
|
+
"default": "./src/plugin/withRepack.js"
|
|
19
22
|
}
|
|
20
23
|
},
|
|
21
24
|
"bin": {
|
|
@@ -37,14 +40,11 @@
|
|
|
37
40
|
"@babel/core": "^7.20.0",
|
|
38
41
|
"@callstack/repack": "^5.2.5",
|
|
39
42
|
"@callstack/repack-plugin-expo-modules": "^5.2.5",
|
|
40
|
-
"@
|
|
41
|
-
"@module-federation/enhanced": "^2.3.1",
|
|
43
|
+
"@module-federation/enhanced": "^2.4.0",
|
|
42
44
|
"@rspack/core": "^1.7.8",
|
|
43
45
|
"@swc/core": "^1.7.0",
|
|
44
46
|
"@swc/helpers": "^0.5.11",
|
|
45
47
|
"adm-zip": "^0.5.10",
|
|
46
|
-
"babel-loader": "^9.1.3",
|
|
47
|
-
"babel-plugin-transform-define": "^2.1.4",
|
|
48
48
|
"babel-preset-expo": "~12.0.0",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"commander": "^11.1.0",
|
|
@@ -38,6 +38,13 @@ async function renameProject(targetDir, newName) {
|
|
|
38
38
|
if (appJson.expo.android) {
|
|
39
39
|
appJson.expo.android.package = `com.anonymous.${newName.replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
// Auto-register ESAD Expo Config Plugin
|
|
43
|
+
if (!appJson.expo.plugins) appJson.expo.plugins = [];
|
|
44
|
+
if (!appJson.expo.plugins.includes('@codemoreira/esad/expo-plugin')) {
|
|
45
|
+
appJson.expo.plugins.push('@codemoreira/esad/expo-plugin');
|
|
46
|
+
console.log(`β
Registered @codemoreira/esad/expo-plugin in app.json.`);
|
|
47
|
+
}
|
|
41
48
|
} else {
|
|
42
49
|
appJson.name = newName;
|
|
43
50
|
appJson.slug = newName;
|
|
@@ -60,44 +67,32 @@ async function renameProject(targetDir, newName) {
|
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
/**
|
|
63
|
-
* Prepares the native folders and applies Re.Pack patches
|
|
70
|
+
* Prepares the native folders and applies Re.Pack patches via Config Plugin
|
|
64
71
|
*/
|
|
65
72
|
async function prepareNative(cwd, platform = 'android') {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
await runProcess('npx', ['expo', 'prebuild', '--platform', 'android'], cwd);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Apply Gradle Patch (Android)
|
|
72
|
-
const buildGradlePath = path.join(cwd, 'android/app/build.gradle');
|
|
73
|
-
if (fs.existsSync(buildGradlePath)) {
|
|
74
|
-
let content = await fs.readFile(buildGradlePath, 'utf8');
|
|
75
|
-
if (!content.includes('project.ext.react')) {
|
|
76
|
-
const patch = `\nproject.ext.react = [\n bundleCommand: "repack-bundle",\n bundleConfig: "rspack.config.mjs"\n]\n\n`;
|
|
77
|
-
content = content.replace(/react \{/, `${patch}react {`);
|
|
78
|
-
|
|
79
|
-
// Force androidx.core version to avoid SDK 36 requirement conflict
|
|
80
|
-
if (!content.includes('androidx.core:core:')) {
|
|
81
|
-
const forcePatch = `\nconfigurations.all {\n resolutionStrategy {\n force 'androidx.core:core:1.15.0'\n force 'androidx.core:core-ktx:1.15.0'\n }\n}\n\n`;
|
|
82
|
-
content = forcePatch + content;
|
|
83
|
-
}
|
|
73
|
+
const hasAndroid = fs.existsSync(path.join(cwd, 'android'));
|
|
74
|
+
const hasIos = fs.existsSync(path.join(cwd, 'ios'));
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
if ((!hasAndroid && (platform === 'android' || platform === 'all')) ||
|
|
77
|
+
(!hasIos && (platform === 'ios' || platform === 'all'))) {
|
|
78
|
+
|
|
79
|
+
console.log(`\nπ¦ Native folder(s) missing. Running expo prebuild...`);
|
|
80
|
+
await runProcess('npx', ['expo', 'prebuild', '--platform', platform === 'all' ? 'all' : platform], cwd);
|
|
88
81
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
82
|
+
// FIX SCRIPTS: Revert Expo's overwrite and point to ESAD CLI
|
|
83
|
+
console.log(`\nπ§Ή Cleaning up package.json scripts (pointing to ESAD CLI)...`);
|
|
84
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
85
|
+
if (fs.existsSync(pkgPath)) {
|
|
86
|
+
const pkg = await fs.readJson(pkgPath);
|
|
87
|
+
pkg.scripts.android = 'esad dev --platform android';
|
|
88
|
+
pkg.scripts.ios = 'esad dev --platform ios';
|
|
89
|
+
pkg.scripts.start = 'esad dev';
|
|
90
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
91
|
+
console.log(`β
Scripts updated to use ESAD CLI (start, android, ios).`);
|
|
97
92
|
}
|
|
98
93
|
}
|
|
99
94
|
|
|
100
|
-
// Create react-native.config.js if missing
|
|
95
|
+
// Create react-native.config.js if missing (Essential for Re.Pack commands)
|
|
101
96
|
const rnConfigPath = path.join(cwd, 'react-native.config.js');
|
|
102
97
|
if (!fs.existsSync(rnConfigPath)) {
|
|
103
98
|
const content = `module.exports = {\n commands: require('@callstack/repack/commands/rspack'),\n};\n`;
|
package/src/plugin/index.js
CHANGED
|
@@ -1,174 +1,83 @@
|
|
|
1
|
-
const path = require('node:path');
|
|
2
|
-
const fs = require('node:fs');
|
|
3
|
-
const Repack = require('@callstack/repack');
|
|
4
|
-
const { ExpoModulesPlugin } = require('@callstack/repack-plugin-expo-modules');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @param {Object}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
test: /\.[cm]?[jt]sx?$/,
|
|
89
|
-
include: [dirname],
|
|
90
|
-
exclude: [/node_modules/],
|
|
91
|
-
type: 'javascript/auto',
|
|
92
|
-
use: {
|
|
93
|
-
loader: '@callstack/repack/babel-swc-loader',
|
|
94
|
-
options: {
|
|
95
|
-
babelrc: true,
|
|
96
|
-
sourceType: 'unambiguous',
|
|
97
|
-
presets: [
|
|
98
|
-
['babel-preset-expo', { platform }],
|
|
99
|
-
],
|
|
100
|
-
caller: { name: 'repack', platform },
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
...Repack.getJsTransformRules(),
|
|
105
|
-
]
|
|
106
|
-
},
|
|
107
|
-
...Repack.getAssetTransformRules(),
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
plugins: [
|
|
111
|
-
new DefinePlugin({
|
|
112
|
-
'__EXPO_OS__': JSON.stringify(platform),
|
|
113
|
-
'__NODE_ENV__': JSON.stringify(isDev ? 'development' : 'production'),
|
|
114
|
-
'__REPACK_PLATFORM__': JSON.stringify(platform),
|
|
115
|
-
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
|
|
116
|
-
'process.env.EXPO_OS': JSON.stringify(platform),
|
|
117
|
-
'process.env.REPACK_PLATFORM': JSON.stringify(platform),
|
|
118
|
-
'__DEV__': JSON.stringify(isDev),
|
|
119
|
-
}),
|
|
120
|
-
new ExpoModulesPlugin(),
|
|
121
|
-
new Repack.RepackPlugin(),
|
|
122
|
-
new Repack.plugins.ModuleFederationPluginV2({
|
|
123
|
-
name: id,
|
|
124
|
-
filename: `${id}.container.js.bundle`,
|
|
125
|
-
remotes: options.remotes || {},
|
|
126
|
-
...(options.type === 'module' ? { exposes: options.exposes || {} } : {}),
|
|
127
|
-
dts: false,
|
|
128
|
-
dev: isDev,
|
|
129
|
-
shared: {
|
|
130
|
-
'react': { singleton: true, eager: true, requiredVersion: pkg.dependencies.react },
|
|
131
|
-
'react/jsx-runtime': { singleton: true, eager: true, requiredVersion: pkg.dependencies.react },
|
|
132
|
-
'react-native': { singleton: true, eager: true, requiredVersion: pkg.dependencies['react-native'] },
|
|
133
|
-
'react-native-safe-area-context': { singleton: true, eager: true, requiredVersion: pkg.dependencies['react-native-safe-area-context'] },
|
|
134
|
-
'@codemoreira/esad/client': {
|
|
135
|
-
singleton: true,
|
|
136
|
-
eager: options.type === 'host',
|
|
137
|
-
version: sdkPkg.version,
|
|
138
|
-
requiredVersion: sdkPkg.version,
|
|
139
|
-
import: clientPath
|
|
140
|
-
},
|
|
141
|
-
...(options.shared || {})
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
],
|
|
145
|
-
experiments: {
|
|
146
|
-
parallelLoader: false,
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// Add Host-specific DevServer magic for Expo
|
|
151
|
-
if (options.type === 'host') {
|
|
152
|
-
config.devServer = {
|
|
153
|
-
setupMiddlewares: (middlewares) => {
|
|
154
|
-
middlewares.unshift((req, res, next) => {
|
|
155
|
-
if (req.url.startsWith('/.expo/.virtual-metro-entry.bundle')) {
|
|
156
|
-
const query = req.url.split('?')[1];
|
|
157
|
-
const isMap = req.url.includes('.map');
|
|
158
|
-
const target = isMap ? '/index.bundle.map' : '/index.bundle';
|
|
159
|
-
const location = query ? `${target}?${query}` : target;
|
|
160
|
-
res.writeHead(302, { Location: location });
|
|
161
|
-
res.end();
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
next();
|
|
165
|
-
});
|
|
166
|
-
return middlewares;
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return config;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
module.exports = { withESAD };
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const Repack = require('@callstack/repack');
|
|
4
|
+
const { ExpoModulesPlugin } = require('@callstack/repack-plugin-expo-modules');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ESAD Re.Pack Plugin Wrapper (v2.0 - POC Mirror)
|
|
8
|
+
* Totalmente alinhado com a POC funcional para Expo 52 + Re.Pack 5.
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} env Rspack environment
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
*/
|
|
13
|
+
function withESAD(env, options) {
|
|
14
|
+
const { platform, dev } = env;
|
|
15
|
+
const isDev = dev !== false;
|
|
16
|
+
|
|
17
|
+
const dirname = options.dirname;
|
|
18
|
+
const pkgPath = path.resolve(dirname, 'package.json');
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
20
|
+
const id = options.id.replace(/-/g, '_');
|
|
21
|
+
|
|
22
|
+
const sdkPkgPath = path.resolve(__dirname, '..', '..', 'package.json');
|
|
23
|
+
const sdkPkg = JSON.parse(fs.readFileSync(sdkPkgPath, 'utf8'));
|
|
24
|
+
const clientPath = path.resolve(__dirname, '..', 'client', 'index.js');
|
|
25
|
+
|
|
26
|
+
return Repack.defineRspackConfig({
|
|
27
|
+
context: dirname,
|
|
28
|
+
mode: isDev ? 'development' : 'production',
|
|
29
|
+
entry: options.entry || './index.js',
|
|
30
|
+
resolve: {
|
|
31
|
+
...Repack.getResolveOptions(),
|
|
32
|
+
conditionNames: ['require', 'import', 'module', 'browser', 'react-native'],
|
|
33
|
+
exportsFields: ['exports'],
|
|
34
|
+
},
|
|
35
|
+
module: {
|
|
36
|
+
rules: [
|
|
37
|
+
{
|
|
38
|
+
test: /\.[cm]?[jt]sx?$/,
|
|
39
|
+
type: 'javascript/auto',
|
|
40
|
+
use: {
|
|
41
|
+
loader: '@callstack/repack/babel-swc-loader',
|
|
42
|
+
options: {
|
|
43
|
+
parallel: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
...Repack.getAssetTransformRules(),
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
plugins: [
|
|
51
|
+
new Repack.RepackPlugin(),
|
|
52
|
+
new Repack.plugins.ModuleFederationPluginV2({
|
|
53
|
+
name: id,
|
|
54
|
+
filename: `${id}.container.js.bundle`,
|
|
55
|
+
remotes: options.remotes || {},
|
|
56
|
+
...(options.type === 'module' ? {
|
|
57
|
+
exposes: options.exposes || {
|
|
58
|
+
'./Main': options.entry || './index.js'
|
|
59
|
+
}
|
|
60
|
+
} : {}),
|
|
61
|
+
dts: false,
|
|
62
|
+
dev: isDev,
|
|
63
|
+
shared: {
|
|
64
|
+
'react': { singleton: true, eager: true, requiredVersion: pkg.dependencies.react },
|
|
65
|
+
'react/jsx-runtime': { singleton: true, eager: true, requiredVersion: pkg.dependencies.react },
|
|
66
|
+
'react-native': { singleton: true, eager: true, requiredVersion: pkg.dependencies['react-native'] },
|
|
67
|
+
'react-native-safe-area-context': { singleton: true, eager: true, requiredVersion: pkg.dependencies['react-native-safe-area-context'] },
|
|
68
|
+
'@codemoreira/esad/client': {
|
|
69
|
+
singleton: true,
|
|
70
|
+
eager: options.type === 'host',
|
|
71
|
+
version: sdkPkg.version,
|
|
72
|
+
requiredVersion: sdkPkg.version,
|
|
73
|
+
import: clientPath
|
|
74
|
+
},
|
|
75
|
+
...(options.shared || {})
|
|
76
|
+
}
|
|
77
|
+
}),
|
|
78
|
+
new ExpoModulesPlugin(),
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = { withESAD };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const { withAppBuildGradle, withProjectBuildGradle, withMainApplication, withMainActivity, withGradleProperties, withAndroidManifest } = require('@expo/config-plugins');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ESAD Expo Config Plugin
|
|
5
|
+
* Automates native patches for Re.Pack 5 + Expo 52.
|
|
6
|
+
*/
|
|
7
|
+
const withESADRepack = (config) => {
|
|
8
|
+
// 1. Disable New Architecture (Fabric) for stability with MF
|
|
9
|
+
config = withGradleProperties(config, (config) => {
|
|
10
|
+
config.modResults = config.modResults.map((item) => {
|
|
11
|
+
if (item.key === 'newArchEnabled') {
|
|
12
|
+
return { ...item, value: 'false' };
|
|
13
|
+
}
|
|
14
|
+
return item;
|
|
15
|
+
});
|
|
16
|
+
return config;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// 2. Adjust root build.gradle (Kotlin 1.9.25 for Compose Compiler)
|
|
20
|
+
config = withProjectBuildGradle(config, (config) => {
|
|
21
|
+
if (config.modResults.language === 'groovy') {
|
|
22
|
+
config.modResults.contents = config.modResults.contents.replace(
|
|
23
|
+
/kotlinVersion = findProperty\('android\.kotlinVersion'\) \?: '.+?'/,
|
|
24
|
+
"kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.25'"
|
|
25
|
+
);
|
|
26
|
+
config.modResults.contents = config.modResults.contents.replace(
|
|
27
|
+
/classpath\('org\.jetbrains\.kotlin:kotlin-gradle-plugin'\)/,
|
|
28
|
+
'classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return config;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// 3. Adjust app/build.gradle (bundleCommand and ABI Filters)
|
|
35
|
+
config = withAppBuildGradle(config, (config) => {
|
|
36
|
+
if (config.modResults.language === 'groovy') {
|
|
37
|
+
let contents = config.modResults.contents;
|
|
38
|
+
|
|
39
|
+
if (!contents.includes('bundleCommand = "repack-bundle"')) {
|
|
40
|
+
contents = contents.replace(
|
|
41
|
+
/react \{/,
|
|
42
|
+
'react {\n bundleCommand = "repack-bundle"\n bundleConfig = "rspack.config.mjs"'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!contents.includes('abiFilters')) {
|
|
47
|
+
contents = contents.replace(
|
|
48
|
+
/defaultConfig \{/,
|
|
49
|
+
'defaultConfig {\n ndk {\n abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"\n }'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
config.modResults.contents = contents;
|
|
54
|
+
}
|
|
55
|
+
return config;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// 4. Android Manifest (Cleartext Traffic for Dev Server)
|
|
59
|
+
config = withAndroidManifest(config, (config) => {
|
|
60
|
+
const mainApplication = config.modResults.manifest.application[0];
|
|
61
|
+
mainApplication.$['android:usesCleartextTraffic'] = 'true';
|
|
62
|
+
return config;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// 5. MainApplication (JS Main Module Name)
|
|
66
|
+
config = withMainApplication(config, (config) => {
|
|
67
|
+
if (config.modResults.language === 'kotlin' || config.modResults.language === 'kt') {
|
|
68
|
+
config.modResults.contents = config.modResults.contents.replace(
|
|
69
|
+
/getJSMainModuleName\(\): String = .*/,
|
|
70
|
+
'getJSMainModuleName(): String = "index"'
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return config;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 6. MainActivity (Main Component Name Sync)
|
|
77
|
+
config = withMainActivity(config, (config) => {
|
|
78
|
+
if (config.modResults.language === 'kotlin' || config.modResults.language === 'kt') {
|
|
79
|
+
config.modResults.contents = config.modResults.contents.replace(
|
|
80
|
+
/getMainComponentName\(\): String = .*/,
|
|
81
|
+
`getMainComponentName(): String = "${config.name}"`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return config;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return config;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
module.exports = withESADRepack;
|
package/src/plugin/env-shim.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ESAD Runtime Environment Shim
|
|
3
|
-
* Injected at the very beginning of the bundle to prevent "TypeError: right operand of 'in' is not an object"
|
|
4
|
-
*/
|
|
5
|
-
var g = typeof globalThis !== 'undefined' ? globalThis : (typeof global !== 'undefined' ? global : this);
|
|
6
|
-
if (!g['process']) {
|
|
7
|
-
g['process'] = {};
|
|
8
|
-
}
|
|
9
|
-
if (!g['process']['env']) {
|
|
10
|
-
g['process']['env'] = {};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
g['process']['env']['EXPO_OS'] = '__EXPO_OS__';
|
|
14
|
-
g['process']['env']['NODE_ENV'] = '__NODE_ENV__';
|
|
15
|
-
g['process']['env']['REPACK_PLATFORM'] = '__REPACK_PLATFORM__';
|
|
16
|
-
|
|
17
|
-
|