Skip to content

Commit c1b3918

Browse files
feat: enhance SharePlugin with unified API improvements for PR8
- Added comprehensive validation for shared configuration - Enhanced error handling in SharePlugin.apply() method - Added helper methods for debugging and introspection - Created comprehensive compiler-unit tests - Updated jest configuration to include compiler-unit tests - Fixed test issues with proper mocking of child plugins All SharePlugin tests passing (25 tests total) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 5ac18a4 commit c1b3918

File tree

5 files changed

+566
-10
lines changed

5 files changed

+566
-10
lines changed

packages/enhanced/jest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default {
3636
testMatch: [
3737
'<rootDir>/test/*.basictest.js',
3838
'<rootDir>/test/unit/**/*.test.ts',
39+
'<rootDir>/test/compiler-unit/**/*.test.ts',
3940
],
4041

4142
testEnvironment: path.resolve(__dirname, './test/patch-node-env.js'),

packages/enhanced/src/lib/sharing/SharePlugin.ts

Lines changed: 105 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,33 @@ class SharePlugin {
3232
private _shareScope: string | string[];
3333
private _consumes: Record<string, ConsumesConfig>[];
3434
private _provides: Record<string, ProvidesConfig>[];
35+
private _options: SharePluginOptions;
3536

3637
constructor(options: SharePluginOptions) {
38+
// Validate options first
3739
validate(options);
3840

41+
// Store options for debugging and introspection
42+
this._options = options;
43+
44+
// Validate shared configuration
45+
if (
46+
!options.shared ||
47+
(typeof options.shared === 'object' &&
48+
Object.keys(options.shared).length === 0)
49+
) {
50+
throw new Error(
51+
'SharePlugin requires at least one shared module configuration',
52+
);
53+
}
54+
3955
const sharedOptions: [string, SharedConfig][] = parseOptions(
4056
options.shared,
4157
(item, key) => {
4258
if (typeof item !== 'string')
43-
throw new Error('Unexpected array in shared');
59+
throw new Error(
60+
`Unexpected array in shared configuration for key "${key}"`,
61+
);
4462
const config: SharedConfig =
4563
item === key || !isRequiredVersion(item)
4664
? {
@@ -52,7 +70,15 @@ class SharePlugin {
5270
};
5371
return config;
5472
},
55-
(item) => item,
73+
(item, key) => {
74+
// Enhanced validation for shared config
75+
if (item.include && item.exclude) {
76+
throw new Error(
77+
`Cannot specify both include and exclude filters for shared module "${key}"`,
78+
);
79+
}
80+
return item;
81+
},
5682
);
5783
const consumes: Record<string, ConsumesConfig>[] = sharedOptions.map(
5884
([key, options]) => ({
@@ -100,6 +126,62 @@ class SharePlugin {
100126
this._provides = provides;
101127
}
102128

129+
/**
130+
* Get the configuration used to initialize this plugin
131+
* @returns The original SharePluginOptions
132+
*/
133+
getOptions(): SharePluginOptions {
134+
return this._options;
135+
}
136+
137+
/**
138+
* Get the share scope name(s) used by this plugin
139+
* @returns The share scope name or array of names
140+
*/
141+
getShareScope(): string | string[] {
142+
return this._shareScope;
143+
}
144+
145+
/**
146+
* Get the consume configurations generated by this plugin
147+
* @returns Array of consume configurations
148+
*/
149+
getConsumes(): Record<string, ConsumesConfig>[] {
150+
return this._consumes;
151+
}
152+
153+
/**
154+
* Get the provide configurations generated by this plugin
155+
* @returns Array of provide configurations
156+
*/
157+
getProvides(): Record<string, ProvidesConfig>[] {
158+
return this._provides;
159+
}
160+
161+
/**
162+
* Get information about shared modules
163+
* @returns Object containing shared module information
164+
*/
165+
getSharedInfo(): {
166+
totalShared: number;
167+
consumeOnly: number;
168+
provideAndConsume: number;
169+
shareScopes: string[];
170+
} {
171+
const consumeOnlyCount = this._consumes.length - this._provides.length;
172+
const provideAndConsumeCount = this._provides.length;
173+
const shareScopes = Array.isArray(this._shareScope)
174+
? this._shareScope
175+
: [this._shareScope];
176+
177+
return {
178+
totalShared: this._consumes.length,
179+
consumeOnly: consumeOnlyCount,
180+
provideAndConsume: provideAndConsumeCount,
181+
shareScopes: shareScopes,
182+
};
183+
}
184+
103185
/**
104186
* Applies the plugin to the webpack compiler instance
105187
* @param compiler - The webpack compiler instance
@@ -108,14 +190,27 @@ class SharePlugin {
108190
process.env['FEDERATION_WEBPACK_PATH'] =
109191
process.env['FEDERATION_WEBPACK_PATH'] || getWebpackPath(compiler);
110192

111-
new ConsumeSharedPlugin({
112-
shareScope: this._shareScope,
113-
consumes: this._consumes,
114-
}).apply(compiler);
115-
new ProvideSharedPlugin({
116-
shareScope: this._shareScope,
117-
provides: this._provides,
118-
}).apply(compiler);
193+
// Apply ConsumeSharedPlugin with enhanced error handling
194+
try {
195+
new ConsumeSharedPlugin({
196+
shareScope: this._shareScope,
197+
consumes: this._consumes,
198+
}).apply(compiler);
199+
} catch (error) {
200+
const message = error instanceof Error ? error.message : String(error);
201+
throw new Error(`Failed to apply ConsumeSharedPlugin: ${message}`);
202+
}
203+
204+
// Apply ProvideSharedPlugin with enhanced error handling
205+
try {
206+
new ProvideSharedPlugin({
207+
shareScope: this._shareScope,
208+
provides: this._provides,
209+
}).apply(compiler);
210+
} catch (error) {
211+
const message = error instanceof Error ? error.message : String(error);
212+
throw new Error(`Failed to apply ProvideSharedPlugin: ${message}`);
213+
}
119214
}
120215
}
121216

0 commit comments

Comments
 (0)