@touk/federated-types 1.2.2-beta.1 → 1.3.0-beta.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 +41 -4
- package/cli.js +69 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ It's recommended that you spread these properties into your ModuleFederationPlug
|
|
|
30
30
|
```javascript
|
|
31
31
|
//webpack.config.js
|
|
32
32
|
|
|
33
|
-
const deps = require('../package.json').dependencies;
|
|
34
33
|
const federationConfig = require('./federation.config.json');
|
|
35
34
|
|
|
36
35
|
module.exports = {
|
|
@@ -40,9 +39,7 @@ module.exports = {
|
|
|
40
39
|
new ModuleFederationPlugin({
|
|
41
40
|
...federationConfig,
|
|
42
41
|
filename: "remoteEntry.js",
|
|
43
|
-
shared: {
|
|
44
|
-
...deps,
|
|
45
|
-
},
|
|
42
|
+
shared: { ... },
|
|
46
43
|
}),
|
|
47
44
|
],
|
|
48
45
|
|
|
@@ -84,3 +81,43 @@ scripts: {
|
|
|
84
81
|
"make-types": "make-federated-types --config ./path/to/my/config.json --outputDir ../../my_types/"
|
|
85
82
|
}
|
|
86
83
|
```
|
|
84
|
+
|
|
85
|
+
## Inline configuration (without config file)
|
|
86
|
+
|
|
87
|
+
If you prefer not to maintain a separate `federation.config.json` file, you can provide the configuration directly via CLI arguments using `--name` and `--exposes`:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
make-federated-types \
|
|
91
|
+
--name myApp \
|
|
92
|
+
--exposes App ./src/App.tsx \
|
|
93
|
+
--exposes Button ./src/components/Button.tsx \
|
|
94
|
+
--outputDir ./types
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Inline config features:
|
|
98
|
+
|
|
99
|
+
- **Multiple exposures**: Use `--exposes` multiple times, each followed by a key and file path
|
|
100
|
+
- **Auto-prefix**: Keys without `./` prefix are automatically normalized (e.g., `App` becomes `./App`)
|
|
101
|
+
- **Shell-friendly**: Works with tab completion for file paths
|
|
102
|
+
- **Priority**: Inline config takes precedence over `--config` and auto-discovery
|
|
103
|
+
|
|
104
|
+
### Examples:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Simple inline config
|
|
108
|
+
make-federated-types --name app2 --exposes Button ./src/Button.tsx
|
|
109
|
+
|
|
110
|
+
# Multiple exposures
|
|
111
|
+
make-federated-types \
|
|
112
|
+
--name app2 \
|
|
113
|
+
--exposes ./Button ./src/Button.tsx \
|
|
114
|
+
--exposes ./Header ./src/Header.tsx
|
|
115
|
+
|
|
116
|
+
# Nested keys (auto-prefixed with ./)
|
|
117
|
+
make-federated-types \
|
|
118
|
+
--name app2 \
|
|
119
|
+
--exposes components/Button ./src/components/Button.tsx \
|
|
120
|
+
--exposes utils/helpers ./src/utils/helpers.ts
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Note**: When using inline config, both `--name` and at least one `--exposes` are required.
|
package/cli.js
CHANGED
|
@@ -29,6 +29,26 @@ const getArg = (argName) => {
|
|
|
29
29
|
const argIndex = process.argv.indexOf(argName);
|
|
30
30
|
return argIndex !== -1 ? process.argv[argIndex + 1] : null;
|
|
31
31
|
};
|
|
32
|
+
const getAllArgs = (argName) => {
|
|
33
|
+
const results = [];
|
|
34
|
+
let i = 2; // process.argv starts with node and script path
|
|
35
|
+
|
|
36
|
+
while (i < process.argv.length) {
|
|
37
|
+
if (process.argv[i] === argName) {
|
|
38
|
+
// Next two arguments are key and value
|
|
39
|
+
if (i + 2 < process.argv.length) {
|
|
40
|
+
results.push([process.argv[i + 1], process.argv[i + 2]]);
|
|
41
|
+
i += 3; // skip argName, key, value
|
|
42
|
+
} else {
|
|
43
|
+
console.error(`ERROR: --exposes requires two arguments (key path)`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return results;
|
|
51
|
+
};
|
|
32
52
|
|
|
33
53
|
const nodeModulesOutputDir = path.resolve(nodeModules, '@types/__federated_types/');
|
|
34
54
|
const saveToNodeMoulesArg = hasArg('--saveToNodeModules');
|
|
@@ -44,6 +64,9 @@ const outputDirs =
|
|
|
44
64
|
const configPathArg = getArg('--config');
|
|
45
65
|
const configPath = configPathArg ? path.resolve(configPathArg) : null;
|
|
46
66
|
|
|
67
|
+
const nameArg = getArg('--name');
|
|
68
|
+
const exposesArgs = getAllArgs('--exposes');
|
|
69
|
+
|
|
47
70
|
const findFederationConfig = (base) => {
|
|
48
71
|
let files = fs.readdirSync(base);
|
|
49
72
|
let queue = [];
|
|
@@ -63,21 +86,52 @@ const findFederationConfig = (base) => {
|
|
|
63
86
|
}
|
|
64
87
|
};
|
|
65
88
|
|
|
66
|
-
|
|
67
|
-
console.error(`ERROR: Unable to find a provided config: ${configPath}`);
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
89
|
+
let federationConfig;
|
|
70
90
|
|
|
71
|
-
|
|
91
|
+
// Priority: inline config > --config > auto-find
|
|
92
|
+
if (nameArg || exposesArgs.length > 0) {
|
|
93
|
+
// Inline config mode
|
|
94
|
+
if (!nameArg || exposesArgs.length === 0) {
|
|
95
|
+
console.error('ERROR: Both --name and --exposes are required for inline config');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
72
98
|
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
99
|
+
if (configPath) {
|
|
100
|
+
console.warn('WARNING: Both inline config and --config provided. Using inline config.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const exposes = {};
|
|
77
104
|
|
|
78
|
-
|
|
105
|
+
exposesArgs.forEach(([key, value]) => {
|
|
106
|
+
// Normalize key - add ./ if missing
|
|
107
|
+
const normalizedKey = key.startsWith('./') ? key : `./${key}`;
|
|
108
|
+
exposes[normalizedKey] = value;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
federationConfig = {
|
|
112
|
+
name: nameArg,
|
|
113
|
+
exposes: exposes,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
console.log('Using inline config:', JSON.stringify(federationConfig, null, 2));
|
|
117
|
+
} else {
|
|
118
|
+
// File-based config (current behavior)
|
|
119
|
+
if (configPath && !fs.existsSync(configPath)) {
|
|
120
|
+
console.error(`ERROR: Unable to find a provided config: ${configPath}`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const federationConfigPath = configPath || findFederationConfig('./');
|
|
125
|
+
|
|
126
|
+
if (federationConfigPath === undefined) {
|
|
127
|
+
console.error(`ERROR: Unable to find a federation.config.json file in this package`);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.log(`Using config file: ${federationConfigPath}`);
|
|
132
|
+
federationConfig = require(federationConfigPath);
|
|
133
|
+
}
|
|
79
134
|
|
|
80
|
-
const federationConfig = require(federationConfigPath);
|
|
81
135
|
const compileFiles = Object.values(federationConfig.exposes);
|
|
82
136
|
const compileKeys = Object.keys(federationConfig.exposes);
|
|
83
137
|
|
|
@@ -122,9 +176,10 @@ try {
|
|
|
122
176
|
|
|
123
177
|
moduleNames.forEach((name) => {
|
|
124
178
|
// exposeName - relative name of exposed component (if not found - just take moduleName)
|
|
125
|
-
const [exposeName = name, ...aliases] = compileKeys.filter((key) =>
|
|
126
|
-
federationConfig.exposes[key].
|
|
127
|
-
|
|
179
|
+
const [exposeName = name, ...aliases] = compileKeys.filter((key) => {
|
|
180
|
+
const normalizedPath = federationConfig.exposes[key].replace(/\.(tsx?|jsx?)$/, '');
|
|
181
|
+
return normalizedPath.endsWith(name);
|
|
182
|
+
});
|
|
128
183
|
const regex = RegExp(`"${name}"`, 'g');
|
|
129
184
|
|
|
130
185
|
const moduleDeclareName = getModuleDeclareName(exposeName);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@touk/federated-types",
|
|
3
3
|
"description": "share typings for your federated typescript packages around your mono-repo",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0-beta.1",
|
|
5
5
|
"author": "Julian Wielga <j@touk.pl>",
|
|
6
6
|
"bin": {
|
|
7
7
|
"make-federated-types": "./cli.js"
|