diff --git a/INCREMENTAL_PR_PLAN_REVISED.md b/INCREMENTAL_PR_PLAN_REVISED.md index b7f88c6f6d0..12f424a77a4 100644 --- a/INCREMENTAL_PR_PLAN_REVISED.md +++ b/INCREMENTAL_PR_PLAN_REVISED.md @@ -3,6 +3,8 @@ ## Overview Based on a detailed diff analysis, this document provides a more accurate breakdown of changes into focused, incremental PRs. Each PR represents a distinct feature, fix, or refactor that can be merged independently. +**IMPORTANT**: All PRs should be compared against the `share-filter` branch as the base branch for measuring changes and creating pull requests. + ## Updated PR Sequence ### PR 1: Runtime Safety Fixes @@ -128,6 +130,8 @@ shared: { --- ### PR 6: Fallback Version Support +**Branch from**: `pr5-request-pattern-filtering` +**Compare against**: `share-filter` branch **Size**: Small (~6 files) **Risk**: Low **Type**: Feature @@ -140,7 +144,7 @@ shared: { - Unit tests for fallback version - Integration tests -**Depends on**: PR 4 +**Depends on**: PR 4 and PR 5 **API**: ```javascript diff --git a/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedModule.d.ts b/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedModule.d.ts index f981b947c8b..56d5104f027 100644 --- a/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedModule.d.ts +++ b/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedModule.d.ts @@ -1,3 +1,17 @@ +import type { SemVerRange } from 'webpack/lib/util/semver'; + +export interface ConsumeSharedModuleExcludeOptions { + request?: string | RegExp; + version?: string; + fallbackVersion?: string; +} + +export interface ConsumeSharedModuleIncludeOptions { + request?: string | RegExp; + version?: string; + fallbackVersion?: string; +} + export type ConsumeOptions = { /** * fallback request @@ -51,29 +65,18 @@ export type ConsumeOptions = { */ issuerLayer?: string | null; /** - * Include filters for consuming shared modules + * Filter object for consuming shared modules. + * Modules matching the criteria in this object will be excluded. */ - include?: { - /** - * Version requirement that must be satisfied for the shared module to be included - */ - version?: string; - /** - * Request pattern that must match for the shared module to be included - */ - request?: string | RegExp; - }; + exclude?: ConsumeSharedModuleExcludeOptions; /** - * Exclude filters for consuming shared modules + * Filter object for consuming shared modules. + * Only modules matching the criteria in this object will be included. */ - exclude?: { - /** - * Version requirement that if satisfied will exclude the shared module - */ - version?: string; - /** - * Request pattern that if matched will exclude the shared module - */ - request?: string | RegExp; - }; + include?: ConsumeSharedModuleIncludeOptions; + /** + * Enable reconstructed lookup for node_modules paths for this share item + */ + nodeModulesReconstructedLookup?: boolean; }; +const TYPES = new Set(['consume-shared']); diff --git a/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedPlugin.d.ts b/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedPlugin.d.ts index 4b9310bf17c..4ba358ac47e 100644 --- a/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedPlugin.d.ts +++ b/packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedPlugin.d.ts @@ -41,6 +41,7 @@ export interface IncludeExcludeOptions { version?: string; fallbackVersion?: string; } + /** * Advanced configuration for modules that should be consumed from share scope. */ diff --git a/packages/enhanced/src/declarations/plugins/sharing/ProvideSharedPlugin.d.ts b/packages/enhanced/src/declarations/plugins/sharing/ProvideSharedPlugin.d.ts index dd34bff6e13..5b1d61d5ab3 100644 --- a/packages/enhanced/src/declarations/plugins/sharing/ProvideSharedPlugin.d.ts +++ b/packages/enhanced/src/declarations/plugins/sharing/ProvideSharedPlugin.d.ts @@ -32,6 +32,13 @@ export interface ProvidesObject { */ [k: string]: ProvidesConfig | ProvidesItem; } + +export interface IncludeExcludeOptions { + request?: string | RegExp; + version?: string; + fallbackVersion?: string; +} + /** * Advanced configuration for modules that should be provided as shared modules to the share scope. */ @@ -73,29 +80,15 @@ export interface ProvidesConfig { */ request?: string; /** - * Include filters for providing shared modules. + * Filter for the shared module. + */ + exclude?: IncludeExcludeOptions; + /** + * Filter for the shared module. */ - include?: { - /** - * Version requirement that must be satisfied for the module to be provided. - */ - version?: string; - /** - * Request pattern that must match for the module to be provided. - */ - request?: string | RegExp; - }; + include?: IncludeExcludeOptions; /** - * Exclude filters for providing shared modules. + * Node modules reconstructed lookup. */ - exclude?: { - /** - * Version requirement that if satisfied will exclude the module from being provided. - */ - version?: string; - /** - * Request pattern that if matched will exclude the module from being provided. - */ - request?: string | RegExp; - }; + nodeModulesReconstructedLookup?: any; } diff --git a/packages/enhanced/src/lib/sharing/ConsumeSharedFallbackDependency.ts b/packages/enhanced/src/lib/sharing/ConsumeSharedFallbackDependency.ts index a38dd89e6e3..d5103f4a26f 100644 --- a/packages/enhanced/src/lib/sharing/ConsumeSharedFallbackDependency.ts +++ b/packages/enhanced/src/lib/sharing/ConsumeSharedFallbackDependency.ts @@ -13,11 +13,15 @@ const { dependencies } = require( ) as typeof import('webpack'); class ConsumeSharedFallbackDependency extends dependencies.ModuleDependency { + layer?: string | null; + /** * @param {string} request the request + * @param {string | null} layer the layer for the fallback module */ - constructor(request: string) { + constructor(request: string, layer?: string | null) { super(request); + this.layer = layer; } override get type(): string { diff --git a/packages/enhanced/src/lib/sharing/ConsumeSharedModule.ts b/packages/enhanced/src/lib/sharing/ConsumeSharedModule.ts index 26186d1bef3..94a29b0b488 100644 --- a/packages/enhanced/src/lib/sharing/ConsumeSharedModule.ts +++ b/packages/enhanced/src/lib/sharing/ConsumeSharedModule.ts @@ -52,6 +52,8 @@ const makeSerializable = require( * @property {boolean} eager include the fallback module in a sync way * @property {string | null=} layer Share a specific layer of the module, if the module supports layers * @property {string | null=} issuerLayer Issuer layer in which the module should be resolved + * @property {{ version?: string; fallbackVersion?: string }} exclude Options for excluding certain versions + * @property {{ version?: string; fallbackVersion?: string }} include Options for including only certain versions */ const TYPES = new Set(['consume-shared']); @@ -173,7 +175,10 @@ class ConsumeSharedModule extends Module { this.buildMeta = {}; this.buildInfo = {}; if (this.options.import) { - const dep = new ConsumeSharedFallbackDependency(this.options.import); + const dep = new ConsumeSharedFallbackDependency( + this.options.import, + this.options.layer, + ); if (this.options.eager) { this.addDependency(dep); } else { diff --git a/packages/enhanced/src/lib/sharing/ConsumeSharedPlugin.ts b/packages/enhanced/src/lib/sharing/ConsumeSharedPlugin.ts index 50b641efb7b..a9fe6847dee 100644 --- a/packages/enhanced/src/lib/sharing/ConsumeSharedPlugin.ts +++ b/packages/enhanced/src/lib/sharing/ConsumeSharedPlugin.ts @@ -4,6 +4,13 @@ */ 'use strict'; + +// Hoisted regex constants +const DIRECT_FALLBACK_REGEX = /^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/; +const ABSOLUTE_PATH_REGEX = /^(\/|[A-Za-z]:|\\\\)/; +const RELATIVE_OR_ABSOLUTE_PATH_REGEX = /^(?:\.{1,2}[\\/]|\/|[A-Za-z]:|\\\\)/; +const PACKAGE_NAME_REGEX = /^((?:@[^\\/]+[\\/])?[^\\/]+)/; + import { getWebpackPath, normalizeWebpackPath, @@ -11,15 +18,11 @@ import { import { isRequiredVersion } from '@module-federation/sdk'; import type { Compiler, Compilation, Module } from 'webpack'; import { parseOptions } from '../container/options'; -import { ConsumeSharedPluginOptions } from '../../declarations/plugins/sharing/ConsumeSharedPlugin'; +import type { ConsumeSharedPluginOptions } from '../../declarations/plugins/sharing/ConsumeSharedPlugin'; import { resolveMatchedConfigs } from './resolveMatchedConfigs'; import { getDescriptionFile, getRequiredVersionFromDescriptionFile, - addSingletonFilterWarning, - testRequestFilters, - createLookupKeyForSharing, - extractPathAfterNodeModules, } from './utils'; import type { ResolveOptionsWithDependencyType, @@ -38,6 +41,11 @@ import type { ConsumeOptions } from '../../declarations/plugins/sharing/ConsumeS import { createSchemaValidation } from '../../utils'; import path from 'path'; import { satisfy } from '@module-federation/runtime-tools/runtime-core'; +import { + addSingletonFilterWarning, + testRequestFilters, + createLookupKeyForSharing, +} from './utils'; const ModuleNotFoundError = require( normalizeWebpackPath('webpack/lib/ModuleNotFoundError'), @@ -53,7 +61,7 @@ const WebpackError = require( ) as typeof import('webpack/lib/WebpackError'); const validate = createSchemaValidation( - //eslint-disable-next-line + // eslint-disable-next-line require('../../schemas/sharing/ConsumeSharedPlugin.check.js').validate, () => require('../../schemas/sharing/ConsumeSharedPlugin').default, { @@ -67,14 +75,6 @@ const RESOLVE_OPTIONS: ResolveOptionsWithDependencyType = { }; const PLUGIN_NAME = 'ConsumeSharedPlugin'; -// Helper function to create composite key -function createLookupKey( - request: string, - contextInfo: ModuleFactoryCreateDataContextInfo, -): string { - return createLookupKeyForSharing(request, contextInfo.issuerLayer); -} - class ConsumeSharedPlugin { private _consumes: [string, ConsumeOptions][]; @@ -144,16 +144,297 @@ class ConsumeSharedPlugin { packageName: item.packageName, singleton: !!item.singleton, eager: !!item.eager, + exclude: item.exclude, + include: item.include, issuerLayer: item.issuerLayer ? item.issuerLayer : undefined, layer: item.layer ? item.layer : undefined, request, - include: item.include, - exclude: item.exclude, } as ConsumeOptions; }, ); } + createConsumeSharedModule( + compilation: Compilation, + context: string, + request: string, + config: ConsumeOptions, + ): Promise { + const requiredVersionWarning = (details: string) => { + const error = new WebpackError( + `No required version specified and unable to automatically determine one. ${details}`, + ); + error.file = `shared module ${request}`; + compilation.warnings.push(error); + }; + const directFallback = + config.import && DIRECT_FALLBACK_REGEX.test(config.import); + + const resolver: ResolverWithOptions = compilation.resolverFactory.get( + 'normal', + RESOLVE_OPTIONS as ResolveOptionsWithDependencyType, + ); + + return Promise.all([ + new Promise((resolve) => { + if (!config.import) return resolve(undefined); + const resolveContext = { + fileDependencies: new LazySet(), + contextDependencies: new LazySet(), + missingDependencies: new LazySet(), + }; + resolver.resolve( + {}, + directFallback ? compilation.compiler.context : context, + config.import, + resolveContext, + (err, result) => { + compilation.contextDependencies.addAll( + resolveContext.contextDependencies, + ); + compilation.fileDependencies.addAll( + resolveContext.fileDependencies, + ); + compilation.missingDependencies.addAll( + resolveContext.missingDependencies, + ); + if (err) { + compilation.errors.push( + new ModuleNotFoundError(null, err, { + name: `resolving fallback for shared module ${request}`, + }), + ); + return resolve(undefined); + } + //@ts-ignore + resolve(result); + }, + ); + }), + new Promise((resolve) => { + if (config.requiredVersion !== undefined) { + return resolve(config.requiredVersion); + } + let packageName = config.packageName; + if (packageName === undefined) { + if (ABSOLUTE_PATH_REGEX.test(request)) { + // For relative or absolute requests we don't automatically use a packageName. + // If wished one can specify one with the packageName option. + return resolve(undefined); + } + const match = PACKAGE_NAME_REGEX.exec(request); + if (!match) { + requiredVersionWarning( + 'Unable to extract the package name from request.', + ); + return resolve(undefined); + } + packageName = match[0]; + } + + getDescriptionFile( + compilation.inputFileSystem, + context, + ['package.json'], + (err, result, checkedDescriptionFilePaths) => { + if (err) { + requiredVersionWarning(`Unable to read description file: ${err}`); + return resolve(undefined); + } + const { data } = /** @type {DescriptionFile} */ result || {}; + if (!data) { + if (checkedDescriptionFilePaths?.length) { + requiredVersionWarning( + [ + `Unable to find required version for "${packageName}" in description file/s`, + checkedDescriptionFilePaths.join('\n'), + 'It need to be in dependencies, devDependencies or peerDependencies.', + ].join('\n'), + ); + } else { + requiredVersionWarning( + `Unable to find description file in ${context}.`, + ); + } + + return resolve(undefined); + } + if (data['name'] === packageName) { + // Package self-referencing + return resolve(undefined); + } + const requiredVersion = getRequiredVersionFromDescriptionFile( + data, + packageName, + ); + //TODO: align with webpck semver parser again + // @ts-ignore webpack internal semver has some issue, use runtime semver , related issue: https://github.com/webpack/webpack/issues/17756 + resolve(requiredVersion); + }, + (result) => { + if (!result) return false; + const { data } = result; + const maybeRequiredVersion = getRequiredVersionFromDescriptionFile( + data, + packageName, + ); + return ( + data['name'] === packageName || + typeof maybeRequiredVersion === 'string' + ); + }, + ); + }), + ]).then(([importResolved, requiredVersion]) => { + const currentConfig = { + ...config, + importResolved, + import: importResolved ? config.import : undefined, + requiredVersion, + }; + const consumedModule = new ConsumeSharedModule( + directFallback ? compilation.compiler.context : context, + currentConfig, + ); + + // Check for include version first + if (config.include && typeof config.include.version === 'string') { + if (!importResolved) { + return consumedModule; + } + + return new Promise((resolveFilter) => { + getDescriptionFile( + compilation.inputFileSystem, + path.dirname(importResolved as string), + ['package.json'], + (err, result) => { + if (err) { + return resolveFilter(consumedModule); + } + const { data } = result || {}; + if (!data || !data['version'] || data['name'] !== request) { + return resolveFilter(consumedModule); + } + + // Only include if version satisfies the include constraint + if ( + config.include && + satisfy(data['version'], config.include.version as string) + ) { + // Validate singleton usage with include.version + if ( + config.include && + config.include.version && + config.singleton + ) { + addSingletonFilterWarning( + compilation, + config.shareKey || request, + 'include', + 'version', + config.include.version, + request, // moduleRequest + importResolved, // moduleResource (might be undefined) + ); + } + + return resolveFilter(consumedModule); + } + + // Check fallback version + if ( + config.include && + typeof config.include.fallbackVersion === 'string' && + config.include.fallbackVersion + ) { + if ( + satisfy( + config.include.fallbackVersion, + config.include.version as string, + ) + ) { + return resolveFilter(consumedModule); + } + return resolveFilter( + undefined as unknown as ConsumeSharedModule, + ); + } + + return resolveFilter(undefined as unknown as ConsumeSharedModule); + }, + ); + }); + } + + // Check for exclude version (existing logic) + if (config.exclude && typeof config.exclude.version === 'string') { + if (!importResolved) { + return consumedModule; + } + + if ( + config.exclude && + typeof config.exclude.fallbackVersion === 'string' && + config.exclude.fallbackVersion + ) { + if (satisfy(config.exclude.fallbackVersion, config.exclude.version)) { + return undefined as unknown as ConsumeSharedModule; + } + return consumedModule; + } + + return new Promise((resolveFilter) => { + getDescriptionFile( + compilation.inputFileSystem, + path.dirname(importResolved as string), + ['package.json'], + (err, result) => { + if (err) { + return resolveFilter(consumedModule); + } + const { data } = result || {}; + if (!data || !data['version'] || data['name'] !== request) { + return resolveFilter(consumedModule); + } + + if ( + config.exclude && + typeof config.exclude.version === 'string' && + satisfy(data['version'], config.exclude.version) + ) { + return resolveFilter( + undefined as unknown as ConsumeSharedModule, + ); + } + + // Validate singleton usage with exclude.version + if ( + config.exclude && + config.exclude.version && + config.singleton + ) { + addSingletonFilterWarning( + compilation, + config.shareKey || request, + 'exclude', + 'version', + config.exclude.version, + request, // moduleRequest + importResolved, // moduleResource (might be undefined) + ); + } + + return resolveFilter(consumedModule); + }, + ); + }); + } + + return consumedModule; + }); + } + apply(compiler: Compiler): void { new FederationRuntimePlugin().apply(compiler); process.env['FEDERATION_WEBPACK_PATH'] = @@ -177,229 +458,16 @@ class ConsumeSharedPlugin { prefixedConsumes = prefixed; }, ); - const resolver: ResolverWithOptions = compilation.resolverFactory.get( - 'normal', - RESOLVE_OPTIONS as ResolveOptionsWithDependencyType, - ); - - const createConsumeSharedModule = ( - context: string, - request: string, - config: ConsumeOptions, - ): Promise => { - const requiredVersionWarning = (details: string) => { - const error = new WebpackError( - `No required version specified and unable to automatically determine one. ${details}`, - ); - error.file = `shared module ${request}`; - compilation.warnings.push(error); - }; - const directFallback = - config.import && - /^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/.test(config.import); - return Promise.all([ - new Promise((resolve) => { - if (!config.import) return resolve(undefined); - const resolveContext = { - fileDependencies: new LazySet(), - contextDependencies: new LazySet(), - missingDependencies: new LazySet(), - }; - resolver.resolve( - {}, - directFallback ? compiler.context : context, - config.import, - resolveContext, - (err, result) => { - compilation.contextDependencies.addAll( - resolveContext.contextDependencies, - ); - compilation.fileDependencies.addAll( - resolveContext.fileDependencies, - ); - compilation.missingDependencies.addAll( - resolveContext.missingDependencies, - ); - if (err) { - compilation.errors.push( - new ModuleNotFoundError(null, err, { - name: `resolving fallback for shared module ${request}`, - }), - ); - return resolve(undefined); - } - //@ts-ignore - resolve(result); - }, - ); - }), - new Promise((resolve) => { - if (config.requiredVersion !== undefined) { - return resolve(config.requiredVersion); - } - let packageName = config.packageName; - if (packageName === undefined) { - if (/^(\/|[A-Za-z]:|\\\\)/.test(request)) { - // For relative or absolute requests we don't automatically use a packageName. - // If wished one can specify one with the packageName option. - return resolve(undefined); - } - const match = /^((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(request); - if (!match) { - requiredVersionWarning( - 'Unable to extract the package name from request.', - ); - return resolve(undefined); - } - packageName = match[0]; - } - - getDescriptionFile( - compilation.inputFileSystem, - context, - ['package.json'], - (err, result, checkedDescriptionFilePaths) => { - if (err) { - requiredVersionWarning( - `Unable to read description file: ${err}`, - ); - return resolve(undefined); - } - const { data } = /** @type {DescriptionFile} */ result || {}; - if (!data) { - if (checkedDescriptionFilePaths?.length) { - requiredVersionWarning( - [ - `Unable to find required version for "${packageName}" in description file/s`, - checkedDescriptionFilePaths.join('\n'), - 'It need to be in dependencies, devDependencies or peerDependencies.', - ].join('\n'), - ); - } else { - requiredVersionWarning( - `Unable to find description file in ${context}.`, - ); - } - - return resolve(undefined); - } - if (data['name'] === packageName) { - // Package self-referencing - return resolve(undefined); - } - const requiredVersion = getRequiredVersionFromDescriptionFile( - data, - packageName, - ); - //TODO: align with webpck semver parser again - // @ts-ignore webpack internal semver has some issue, use runtime semver , related issue: https://github.com/webpack/webpack/issues/17756 - resolve(requiredVersion); - }, - (result) => { - if (!result) return false; - const { data } = result; - const maybeRequiredVersion = - getRequiredVersionFromDescriptionFile(data, packageName); - return ( - data['name'] === packageName || - typeof maybeRequiredVersion === 'string' - ); - }, - ); - }), - ]).then(([importResolved, requiredVersion]) => { - // Apply version filters if defined - if (requiredVersion && typeof requiredVersion === 'string') { - // Check include version filter - if (config.include?.version) { - const includeVersion = config.include.version; - if (typeof includeVersion === 'string') { - if (!satisfy(requiredVersion, includeVersion)) { - const error = new WebpackError( - `Shared module "${request}" version "${requiredVersion}" does not satisfy include filter "${includeVersion}"`, - ); - error.file = `shared module ${request}`; - compilation.warnings.push(error); - return new ConsumeSharedModule( - directFallback ? compiler.context : context, - { - ...config, - importResolved: undefined, - import: undefined, - requiredVersion: false, - }, - ); - } - } - } - - // Check exclude version filter - if (config.exclude?.version) { - const excludeVersion = config.exclude.version; - if (typeof excludeVersion === 'string') { - if (satisfy(requiredVersion, excludeVersion)) { - const error = new WebpackError( - `Shared module "${request}" version "${requiredVersion}" matches exclude filter "${excludeVersion}"`, - ); - error.file = `shared module ${request}`; - compilation.warnings.push(error); - return new ConsumeSharedModule( - directFallback ? compiler.context : context, - { - ...config, - importResolved: undefined, - import: undefined, - requiredVersion: false, - }, - ); - } - } - } - - // Check singleton warnings for version filters - if (config.singleton) { - if (config.include?.version) { - addSingletonFilterWarning( - compilation, - config.shareKey, - 'include', - 'version', - config.include.version, - request, - importResolved, - ); - } - if (config.exclude?.version) { - addSingletonFilterWarning( - compilation, - config.shareKey, - 'exclude', - 'version', - config.exclude.version, - request, - importResolved, - ); - } - } - } - - return new ConsumeSharedModule( - directFallback ? compiler.context : context, - { - ...config, - importResolved, - import: importResolved ? config.import : undefined, - requiredVersion, - }, - ); - }); - }; normalModuleFactory.hooks.factorize.tapPromise( PLUGIN_NAME, async (resolveData: ResolveData): Promise => { const { context, request, dependencies, contextInfo } = resolveData; // wait for resolving to be complete + // BIND `this` for createConsumeSharedModule call + const boundCreateConsumeSharedModule = + this.createConsumeSharedModule.bind(this); + return promise.then(() => { if ( dependencies[0] instanceof ConsumeSharedFallbackDependency || @@ -407,29 +475,42 @@ class ConsumeSharedPlugin { ) { return; } - const match = unresolvedConsumes.get( - createLookupKey(request, contextInfo), - ); + const { context, request, contextInfo } = resolveData; + + const match = + unresolvedConsumes.get( + createLookupKeyForSharing(request, contextInfo.issuerLayer), + ) || + unresolvedConsumes.get( + createLookupKeyForSharing(request, undefined), + ); + // First check direct match with original request if (match !== undefined) { - // Apply request filters if defined - if ( - !testRequestFilters( - request, - match.include?.request, - match.exclude?.request, - ) - ) { - return; - } - return createConsumeSharedModule(context, request, match); + // Use the bound function + return boundCreateConsumeSharedModule( + compilation, + context, + request, + match, + ); } + + // Check for prefixed consumes with original request for (const [prefix, options] of prefixedConsumes) { const lookup = options.request || prefix; + // Refined issuerLayer matching logic + if (options.issuerLayer) { + if (!contextInfo.issuerLayer) { + continue; // Option is layered, request is not: skip + } + if (contextInfo.issuerLayer !== options.issuerLayer) { + continue; // Both are layered but do not match: skip + } + } + // If contextInfo.issuerLayer exists but options.issuerLayer does not, allow (non-layered option matches layered request) if (request.startsWith(lookup)) { const remainder = request.slice(lookup.length); - - // Apply request filters if defined if ( !testRequestFilters( remainder, @@ -437,45 +518,26 @@ class ConsumeSharedPlugin { options.exclude?.request, ) ) { - continue; // Skip this match if filters don't pass + continue; } - const shareKey = options.shareKey + remainder; - - // Check singleton warning for request filters - if (options.singleton) { - if (options.include?.request) { - addSingletonFilterWarning( - compilation, - shareKey, - 'include', - 'request', - options.include.request, - request, - ); - } - if (options.exclude?.request) { - addSingletonFilterWarning( - compilation, - shareKey, - 'exclude', - 'request', - options.exclude.request, - request, - ); - } - } - - return createConsumeSharedModule(context, request, { - ...options, - import: options.import - ? options.import + remainder - : undefined, - shareKey, - layer: options.layer || contextInfo.issuerLayer, - }); + // Use the bound function + return boundCreateConsumeSharedModule( + compilation, + context, + request, + { + ...options, + import: options.import + ? options.import + remainder + : undefined, + shareKey: options.shareKey + remainder, + layer: options.layer, + }, + ); } } + return; }); }, @@ -483,6 +545,9 @@ class ConsumeSharedPlugin { normalModuleFactory.hooks.createModule.tapPromise( PLUGIN_NAME, ({ resource }, { context, dependencies }) => { + // BIND `this` for createConsumeSharedModule call + const boundCreateConsumeSharedModule = + this.createConsumeSharedModule.bind(this); if ( dependencies[0] instanceof ConsumeSharedFallbackDependency || dependencies[0] instanceof ProvideForSharedDependency @@ -492,21 +557,13 @@ class ConsumeSharedPlugin { if (resource) { const options = resolvedConsumes.get(resource); if (options !== undefined) { - // Extract request from resource path for filtering - const request = - extractPathAfterNodeModules(resource) || resource; - - // Apply request filters if defined - if ( - !testRequestFilters( - request, - options.include?.request, - options.exclude?.request, - ) - ) { - return Promise.resolve(); - } - return createConsumeSharedModule(context, resource, options); + // Use the bound function + return boundCreateConsumeSharedModule( + compilation, + context, + resource, + options, + ); } } return Promise.resolve(); diff --git a/packages/enhanced/src/lib/sharing/ProvideSharedPlugin.ts b/packages/enhanced/src/lib/sharing/ProvideSharedPlugin.ts index be1e9fa9348..e1f40413e9d 100644 --- a/packages/enhanced/src/lib/sharing/ProvideSharedPlugin.ts +++ b/packages/enhanced/src/lib/sharing/ProvideSharedPlugin.ts @@ -23,13 +23,12 @@ import type { } from '../../declarations/plugins/sharing/ProvideSharedPlugin'; import FederationRuntimePlugin from '../container/runtime/FederationRuntimePlugin'; import { createSchemaValidation } from '../../utils'; -import path from 'path'; import { satisfy } from '@module-federation/runtime-tools/runtime-core'; import { addSingletonFilterWarning, testRequestFilters, createLookupKeyForSharing, - extractPathAfterNodeModules, + getRequiredVersionFromDescriptionFile, } from './utils'; const WebpackError = require( normalizeWebpackPath('webpack/lib/WebpackError'), @@ -61,18 +60,12 @@ const validate = createSchemaValidation( * @property {string | undefined | false} version * @property {boolean} eager * @property {string} [request] The actual request to use for importing the module + * @property {{ version?: string; request?: string | RegExp; fallbackVersion?: string }} [exclude] Options for excluding certain versions or requests + * @property {{ version?: string; request?: string | RegExp; fallbackVersion?: string }} [include] Options for including only certain versions or requests */ /** @typedef {Map} ResolvedProvideMap */ -// Helper function to create composite key -function createLookupKey( - request: string, - config: { layer?: string | null }, -): string { - return createLookupKeyForSharing(request, config.layer); -} - class ProvideSharedPlugin { private _provides: [string, ProvidesConfig][]; @@ -84,10 +77,9 @@ class ProvideSharedPlugin { this._provides = parseOptions( options.provides, - (item) => { + (item): ProvidesConfig => { if (Array.isArray(item)) throw new Error('Unexpected array of provides'); - /** @type {ProvidesConfig} */ const result: ProvidesConfig = { shareKey: item, version: undefined, @@ -98,10 +90,12 @@ class ProvideSharedPlugin { singleton: false, layer: undefined, request: item, + exclude: undefined, + include: undefined, }; return result; }, - (item, key) => { + (item, key): ProvidesConfig => { const request = item.request || key; return { shareScope: item.shareScope || options.shareScope || 'default', @@ -113,8 +107,8 @@ class ProvideSharedPlugin { singleton: !!item.singleton, layer: item.layer, request, - include: item.include, exclude: item.exclude, + include: item.include, }; }, ); @@ -144,132 +138,171 @@ class ProvideSharedPlugin { const resolvedProvideMap: ResolvedProvideMap = new Map(); const matchProvides: Map = new Map(); const prefixMatchProvides: Map = new Map(); + for (const [request, config] of this._provides) { const actualRequest = config.request || request; - const lookupKey = createLookupKey(actualRequest, config); + const lookupKey = createLookupKeyForSharing( + actualRequest, + config.layer, + ); if (/^(\/|[A-Za-z]:\\|\\\\|\.\.?(\/|$))/.test(actualRequest)) { - // relative request - apply filtering if include/exclude are defined - if (this.shouldProvideSharedModule(config)) { - resolvedProvideMap.set(lookupKey, { - config, - version: config.version, - }); - } + resolvedProvideMap.set(lookupKey, { + config, + version: config.version, + resource: actualRequest, + }); } else if (/^(\/|[A-Za-z]:\\|\\\\)/.test(actualRequest)) { - // absolute path - apply filtering if include/exclude are defined - if (this.shouldProvideSharedModule(config)) { - resolvedProvideMap.set(lookupKey, { - config, - version: config.version, - }); - } + resolvedProvideMap.set(lookupKey, { + config, + version: config.version, + resource: actualRequest, + }); } else if (actualRequest.endsWith('/')) { - // module request prefix prefixMatchProvides.set(lookupKey, config); } else { - // module request matchProvides.set(lookupKey, config); } } compilationData.set(compilation, resolvedProvideMap); + normalModuleFactory.hooks.module.tap( 'ProvideSharedPlugin', (module, { resource, resourceResolveData }, resolveData) => { const moduleLayer = module.layer; - const lookupKey = createLookupKey(resource || '', { - layer: moduleLayer || undefined, - }); + const lookupKeyForResource = createLookupKeyForSharing( + resource || '', + moduleLayer || undefined, + ); - if (resource && resolvedProvideMap.has(lookupKey)) { + if (resource && resolvedProvideMap.has(lookupKeyForResource)) { return module; } - const { request } = resolveData; - { - const requestKey = createLookupKey(request, { - layer: moduleLayer || undefined, - }); - const config = matchProvides.get(requestKey); - if (config !== undefined && resource) { - // Apply request filters if defined - if ( - !testRequestFilters( - request, - config.include?.request, - config.exclude?.request, - ) - ) { - return module; - } - this.provideSharedModule( - compilation, - resolvedProvideMap, - request, - config, - resource, - resourceResolveData, - ); - resolveData.cacheable = false; - } + + const { request: originalRequestString } = resolveData; + + // --- Stage 1a: Direct match with originalRequestString --- + const originalRequestLookupKey = createLookupKeyForSharing( + originalRequestString, + moduleLayer || undefined, + ); + const configFromOriginalDirect = matchProvides.get( + originalRequestLookupKey, + ); + + if ( + configFromOriginalDirect !== undefined && + resource && + !resolvedProvideMap.has(lookupKeyForResource) + ) { + this.provideSharedModule( + compilation, + resolvedProvideMap, + originalRequestString, + configFromOriginalDirect, + resource, + resourceResolveData, + ); + resolveData.cacheable = false; } - for (const [prefix, config] of prefixMatchProvides) { - const lookup = config.request || prefix; - if (request.startsWith(lookup) && resource) { - const remainder = request.slice(lookup.length); - - // Apply request filters if defined - if ( - !testRequestFilters( - remainder, - config.include?.request, - config.exclude?.request, - ) - ) { - continue; // Skip this match if filters don't pass + + // --- Stage 1b: Prefix match with originalRequestString --- + if (resource && !resolvedProvideMap.has(lookupKeyForResource)) { + for (const [ + prefixLookupKey, + originalPrefixConfig, + ] of prefixMatchProvides) { + const configuredPrefix = + originalPrefixConfig.request || prefixLookupKey.split('?')[0]; + + // Refined layer matching logic + if (originalPrefixConfig.layer) { + if (!moduleLayer) { + continue; // Option is layered, request is not: skip + } + if (moduleLayer !== originalPrefixConfig.layer) { + continue; // Both are layered but do not match: skip + } } + // If moduleLayer exists but config.layer does not, allow (non-layered option matches layered request) + + if (originalRequestString.startsWith(configuredPrefix)) { + if (resolvedProvideMap.has(lookupKeyForResource)) continue; + + const remainder = originalRequestString.slice( + configuredPrefix.length, + ); + if ( + !testRequestFilters( + remainder, + originalPrefixConfig.include?.request, + originalPrefixConfig.exclude?.request, + ) + ) { + continue; + } - const shareKey = config.shareKey + remainder; + const finalShareKey = + (originalPrefixConfig.shareKey || configuredPrefix) + + remainder; - // Check singleton warning for request filters - if (config.singleton) { - if (config.include?.request) { + // Validate singleton usage when using include.request + if ( + originalPrefixConfig.include?.request && + originalPrefixConfig.singleton + ) { addSingletonFilterWarning( compilation, - shareKey, + finalShareKey, 'include', 'request', - config.include.request, - request, + originalPrefixConfig.include.request, + originalRequestString, resource, ); } - if (config.exclude?.request) { + + // Validate singleton usage when using exclude.request + if ( + originalPrefixConfig.exclude?.request && + originalPrefixConfig.singleton + ) { addSingletonFilterWarning( compilation, - shareKey, + finalShareKey, 'exclude', 'request', - config.exclude.request, - request, + originalPrefixConfig.exclude.request, + originalRequestString, resource, ); } + const configForSpecificModule: ProvidesConfig = { + ...originalPrefixConfig, + shareKey: finalShareKey, + request: originalRequestString, + include: originalPrefixConfig.include + ? { ...originalPrefixConfig.include, request: undefined } + : undefined, + exclude: originalPrefixConfig.exclude + ? { ...originalPrefixConfig.exclude, request: undefined } + : undefined, + }; + + this.provideSharedModule( + compilation, + resolvedProvideMap, + originalRequestString, + configForSpecificModule, + resource, + resourceResolveData, + ); + resolveData.cacheable = false; + break; } - - this.provideSharedModule( - compilation, - resolvedProvideMap, - resource, - { - ...config, - shareKey, - }, - resource, - resourceResolveData, - ); - resolveData.cacheable = false; } } + return module; }, ); @@ -281,9 +314,86 @@ class ProvideSharedPlugin { const resolvedProvideMap = compilationData.get(compilation); if (!resolvedProvideMap) return; + // Filter out modules that don't pass include/exclude conditions + const filteredEntries = Array.from(resolvedProvideMap).filter( + ([resourceKey, { config, version, resource }]) => { + // Apply the same filtering logic as in provideSharedModule + const actualResource = resource || resourceKey; + + // Check include conditions + if (config.include) { + let versionIncludeFailed = false; + if (typeof config.include.version === 'string') { + if (typeof version === 'string' && version) { + if (!satisfy(version, config.include.version)) { + versionIncludeFailed = true; + } + } else { + versionIncludeFailed = true; + } + } + + let requestIncludeFailed = false; + if (config.include.request) { + const includeRequestValue = config.include.request; + const requestActuallyMatches = + includeRequestValue instanceof RegExp + ? includeRequestValue.test(actualResource) + : actualResource === includeRequestValue; + if (!requestActuallyMatches) { + requestIncludeFailed = true; + } + } + + // Skip if any specified include condition failed + const shouldSkipVersion = + typeof config.include.version === 'string' && + versionIncludeFailed; + const shouldSkipRequest = + config.include.request && requestIncludeFailed; + + if (shouldSkipVersion || shouldSkipRequest) { + return false; + } + } + + // Check exclude conditions + if (config.exclude) { + let versionExcludeMatches = false; + if ( + typeof config.exclude.version === 'string' && + typeof version === 'string' && + version + ) { + if (satisfy(version, config.exclude.version)) { + versionExcludeMatches = true; + } + } + + let requestExcludeMatches = false; + if (config.exclude.request) { + const excludeRequestValue = config.exclude.request; + const requestActuallyMatchesExclude = + excludeRequestValue instanceof RegExp + ? excludeRequestValue.test(actualResource) + : actualResource === excludeRequestValue; + if (requestActuallyMatchesExclude) { + requestExcludeMatches = true; + } + } + + // Skip if any specified exclude condition matched + if (versionExcludeMatches || requestExcludeMatches) { + return false; + } + } + + return true; + }, + ); + await Promise.all( - Array.from( - resolvedProvideMap, + filteredEntries.map( ([resourceKey, { config, version, resource }]) => { return new Promise((resolve, reject) => { compilation.addInclude( @@ -351,7 +461,39 @@ class ProvideSharedPlugin { details = 'No description file (usually package.json) found. Add description file with name and version, or manually specify version in shared config.'; } else if (!descriptionFileData.version) { - details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`; + // Try to get version from parent package.json dependencies + if (resourceResolveData.descriptionFilePath) { + try { + const fs = require('fs'); + const path = require('path'); + const parentPkgPath = path.resolve( + path.dirname(resourceResolveData.descriptionFilePath), + '..', + 'package.json', + ); + if (fs.existsSync(parentPkgPath)) { + const parentPkg = JSON.parse( + fs.readFileSync(parentPkgPath, 'utf8'), + ); + const parentVersion = getRequiredVersionFromDescriptionFile( + parentPkg, + key, + ); + if (parentVersion) { + version = parentVersion; + details = `Using version from parent package.json dependencies: ${version}`; + } else { + details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`; + } + } else { + details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`; + } + } catch (e) { + details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`; + } + } else { + details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`; + } } else { version = descriptionFileData.version; } @@ -378,16 +520,24 @@ class ProvideSharedPlugin { } } + let requestIncludeFailed = false; + if (config.include.request) { + const includeRequestValue = config.include.request; + const requestActuallyMatches = + includeRequestValue instanceof RegExp + ? includeRequestValue.test(resource) + : resource === includeRequestValue; + if (!requestActuallyMatches) { + requestIncludeFailed = true; + } + } + // Skip if any specified include condition failed const shouldSkipVersion = typeof config.include.version === 'string' && versionIncludeFailed; + const shouldSkipRequest = config.include.request && requestIncludeFailed; - if (shouldSkipVersion) { - const error = new WebpackError( - `Provided module "${key}" version "${version}" does not satisfy include filter "${config.include.version}"`, - ); - error.file = `shared module ${key} -> ${resource}`; - compilation.warnings.push(error); + if (shouldSkipVersion || shouldSkipRequest) { return; } @@ -399,8 +549,8 @@ class ProvideSharedPlugin { 'include', 'version', config.include.version, - key, - resource, + key, // moduleRequest + resource, // moduleResource ); } } @@ -417,13 +567,20 @@ class ProvideSharedPlugin { } } + let requestExcludeMatches = false; + if (config.exclude.request) { + const excludeRequestValue = config.exclude.request; + const requestActuallyMatchesExclude = + excludeRequestValue instanceof RegExp + ? excludeRequestValue.test(resource) + : resource === excludeRequestValue; + if (requestActuallyMatchesExclude) { + requestExcludeMatches = true; + } + } + // Skip if any specified exclude condition matched - if (versionExcludeMatches) { - const error = new WebpackError( - `Provided module "${key}" version "${version}" matches exclude filter "${config.exclude.version}"`, - ); - error.file = `shared module ${key} -> ${resource}`; - compilation.warnings.push(error); + if (versionExcludeMatches || requestExcludeMatches) { return; } @@ -435,55 +592,18 @@ class ProvideSharedPlugin { 'exclude', 'version', config.exclude.version, - key, - resource, + key, // moduleRequest + resource, // moduleResource ); } } - const lookupKey = createLookupKey(resource, config); + const lookupKey = createLookupKeyForSharing(resource, config.layer); resolvedProvideMap.set(lookupKey, { config, version, resource, }); } - - private shouldProvideSharedModule(config: ProvidesConfig): boolean { - // For static (relative/absolute path) modules, we can only check version filters - // if the version is explicitly provided in the config - if (!config.version) { - // If no version is provided and there are version filters, - // we'll defer to runtime filtering - return true; - } - - const version = config.version; - if (typeof version !== 'string') { - return true; - } - - // Check include version filter - if (config.include?.version) { - const includeVersion = config.include.version; - if (typeof includeVersion === 'string') { - if (!satisfy(version, includeVersion)) { - return false; // Skip providing this module - } - } - } - - // Check exclude version filter - if (config.exclude?.version) { - const excludeVersion = config.exclude.version; - if (typeof excludeVersion === 'string') { - if (satisfy(version, excludeVersion)) { - return false; // Skip providing this module - } - } - } - - return true; // All filters pass - } } export default ProvideSharedPlugin; diff --git a/packages/enhanced/src/lib/sharing/SharePlugin.ts b/packages/enhanced/src/lib/sharing/SharePlugin.ts index b90a9bee20d..0a26f1ccb6e 100644 --- a/packages/enhanced/src/lib/sharing/SharePlugin.ts +++ b/packages/enhanced/src/lib/sharing/SharePlugin.ts @@ -16,6 +16,17 @@ import type { import type { ConsumesConfig } from '../../declarations/plugins/sharing/ConsumeSharedPlugin'; import type { ProvidesConfig } from '../../declarations/plugins/sharing/ProvideSharedPlugin'; import { getWebpackPath } from '@module-federation/sdk/normalize-webpack-path'; +import { createSchemaValidation } from '../../utils'; + +const validate = createSchemaValidation( + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('../../schemas/sharing/SharePlugin.check.js').validate, + () => require('../../schemas/sharing/SharePlugin').default, + { + name: 'Share Plugin', + baseDataPath: 'options', + }, +); class SharePlugin { private _shareScope: string | string[]; @@ -23,6 +34,8 @@ class SharePlugin { private _provides: Record[]; constructor(options: SharePluginOptions) { + validate(options); + const sharedOptions: [string, SharedConfig][] = parseOptions( options.shared, (item, key) => { @@ -55,8 +68,8 @@ class SharePlugin { issuerLayer: options.issuerLayer, layer: options.layer, request: options.request || key, - include: options.include, exclude: options.exclude, + include: options.include, }, }), ); @@ -73,8 +86,8 @@ class SharePlugin { singleton: options.singleton, layer: options.layer, request: options.request || options.import || key, - include: options.include, exclude: options.exclude, + include: options.include, }, })); diff --git a/packages/enhanced/src/lib/sharing/resolveMatchedConfigs.ts b/packages/enhanced/src/lib/sharing/resolveMatchedConfigs.ts index 7779277bf6a..4e4b66e94d6 100644 --- a/packages/enhanced/src/lib/sharing/resolveMatchedConfigs.ts +++ b/packages/enhanced/src/lib/sharing/resolveMatchedConfigs.ts @@ -28,17 +28,16 @@ const RESOLVE_OPTIONS: ResolveOptionsWithDependencyType = { }; function createCompositeKey(request: string, config: ConsumeOptions): string { - if (config.issuerLayer) { - return `(${config.issuerLayer})${request}`; - // layer unlikely to be used, issuerLayer is what factorize provides - // which is what we need to create a matching key for - } else if (config.layer) { - return `(${config.layer})${request}`; - } else { - return request; + // disabling layer as fallback so that we can use issuerLayer to match + // this way we can catch unlayered requests and default them to another layer + // example react -> layered react without (layer)react + const layer = config.issuerLayer; //|| config.layer; + if (layer) { + return `(${layer})${request}`; } + return request; } -// TODO: look at passing dedicated request key instead of infer from object key + export async function resolveMatchedConfigs( compilation: Compilation, configs: [string, T][], @@ -100,5 +99,6 @@ export async function resolveMatchedConfigs( compilation.contextDependencies.addAll(resolveContext.contextDependencies); compilation.fileDependencies.addAll(resolveContext.fileDependencies); compilation.missingDependencies.addAll(resolveContext.missingDependencies); + return { resolved, unresolved, prefixed }; } diff --git a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.check.ts b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.check.ts index 0ada00148b2..29e2430735b 100644 --- a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.check.ts +++ b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.check.ts @@ -236,6 +236,8 @@ const t = { additionalProperties: !1, properties: { eager: { type: 'boolean' }, + exclude: { $ref: '#/definitions/IncludeExcludeOptions' }, + include: { $ref: '#/definitions/IncludeExcludeOptions' }, import: { anyOf: [{ enum: [!1] }, { $ref: '#/definitions/SharedItem' }], }, @@ -254,6 +256,7 @@ const t = { singleton: { type: 'boolean' }, strictVersion: { type: 'boolean' }, version: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, + nodeModulesReconstructedLookup: { type: 'boolean' }, }, }, SharedItem: { type: 'string', minLength: 1 }, @@ -267,6 +270,29 @@ const t = { }, }, UmdNamedDefine: { type: 'boolean' }, + IncludeExcludeOptions: { + type: 'object', + properties: { + request: { type: ['string', 'object'] }, + version: { type: 'string' }, + fallbackVersion: { type: 'string' }, + }, + additionalProperties: !1, + anyOf: [ + { required: ['request'] }, + { required: ['version'] }, + { required: ['fallbackVersion'] }, + ], + }, + Exclude: { + type: 'object', + additionalProperties: !1, + properties: { + request: { instanceof: 'RegExp' }, + version: { type: 'string' }, + fallbackVersion: { type: 'string' }, + }, + }, }, type: 'object', additionalProperties: !1, @@ -1434,29 +1460,46 @@ function g( ); } const h = { - type: 'object', - additionalProperties: !1, - properties: { - eager: { type: 'boolean' }, - import: { anyOf: [{ enum: [!1] }, { $ref: '#/definitions/SharedItem' }] }, - request: { type: 'string', minLength: 1 }, - layer: { type: 'string', minLength: 1 }, - issuerLayer: { type: 'string', minLength: 1 }, - packageName: { type: 'string', minLength: 1 }, - requiredVersion: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, - shareKey: { type: 'string', minLength: 1 }, - shareScope: { - anyOf: [ - { type: 'string', minLength: 1 }, - { type: 'array', items: { type: 'string', minLength: 1 } }, - ], + type: 'object', + additionalProperties: !1, + properties: { + eager: { type: 'boolean' }, + exclude: { $ref: '#/definitions/IncludeExcludeOptions' }, + include: { $ref: '#/definitions/IncludeExcludeOptions' }, + import: { anyOf: [{ enum: [!1] }, { $ref: '#/definitions/SharedItem' }] }, + request: { type: 'string', minLength: 1 }, + layer: { type: 'string', minLength: 1 }, + issuerLayer: { type: 'string', minLength: 1 }, + packageName: { type: 'string', minLength: 1 }, + requiredVersion: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, + shareKey: { type: 'string', minLength: 1 }, + shareScope: { + anyOf: [ + { type: 'string', minLength: 1 }, + { type: 'array', items: { type: 'string', minLength: 1 } }, + ], + }, + singleton: { type: 'boolean' }, + strictVersion: { type: 'boolean' }, + version: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, + nodeModulesReconstructedLookup: { type: 'boolean' }, }, - singleton: { type: 'boolean' }, - strictVersion: { type: 'boolean' }, - version: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, }, -}; -function b( + b = { + type: 'object', + properties: { + request: { type: ['string', 'object'] }, + version: { type: 'string' }, + fallbackVersion: { type: 'string' }, + }, + additionalProperties: !1, + anyOf: [ + { required: ['request'] }, + { required: ['version'] }, + { required: ['fallbackVersion'] }, + ], + }; +function v( e, { instancePath: t = '', @@ -1469,206 +1512,348 @@ function b( i = 0; if (0 === i) { if (!e || 'object' != typeof e || Array.isArray(e)) - return (b.errors = [{ params: { type: 'object' } }]), !1; + return (v.errors = [{ params: { type: 'object' } }]), !1; { const t = i; for (const t in e) if (!s.call(h.properties, t)) - return (b.errors = [{ params: { additionalProperty: t } }]), !1; + return (v.errors = [{ params: { additionalProperty: t } }]), !1; if (t === i) { if (void 0 !== e.eager) { const t = i; if ('boolean' != typeof e.eager) - return (b.errors = [{ params: { type: 'boolean' } }]), !1; + return (v.errors = [{ params: { type: 'boolean' } }]), !1; var l = t === i; } else l = !0; if (l) { - if (void 0 !== e.import) { - let t = e.import; + if (void 0 !== e.exclude) { + let t = e.exclude; const r = i, - n = i; - let s = !1; - const o = i; - if (!1 !== t) { - const e = { - params: { allowedValues: h.properties.import.anyOf[0].enum }, - }; - null === a ? (a = [e]) : a.push(e), i++; + n = i, + s = i; + let o = !1; + const y = i; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if (void 0 === t.request && (e = 'request')) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; + } } - var p = o === i; - if (((s = s || p), !s)) { + var p = y === i; + if (((o = o || p), !o)) { const e = i; - if (i == i) - if ('string' == typeof t) { - if (t.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), i++; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if (void 0 === t.version && (e = 'version')) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; + } + } + if (((p = e === i), (o = o || p), !o)) { + const e = i; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if (void 0 === t.fallbackVersion && (e = 'fallbackVersion')) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), i++; } - (p = e === i), (s = s || p); + (p = e === i), (o = o || p); + } } - if (!s) { + if (!o) { const e = { params: {} }; return ( - null === a ? (a = [e]) : a.push(e), i++, (b.errors = a), !1 + null === a ? (a = [e]) : a.push(e), i++, (v.errors = a), !1 ); } - (i = n), - null !== a && (n ? (a.length = n) : (a = null)), - (l = r === i); + if ( + ((i = s), + null !== a && (s ? (a.length = s) : (a = null)), + i === n) + ) { + if (!t || 'object' != typeof t || Array.isArray(t)) + return (v.errors = [{ params: { type: 'object' } }]), !1; + { + const e = i; + for (const e in t) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) + return ( + (v.errors = [{ params: { additionalProperty: e } }]), !1 + ); + if (e === i) { + if (void 0 !== t.request) { + let e = t.request; + const r = i; + if ( + 'string' != typeof e && + (!e || 'object' != typeof e || Array.isArray(e)) + ) + return ( + (v.errors = [ + { params: { type: b.properties.request.type } }, + ]), + !1 + ); + var f = r === i; + } else f = !0; + if (f) { + if (void 0 !== t.version) { + const e = i; + if ('string' != typeof t.version) + return ( + (v.errors = [{ params: { type: 'string' } }]), !1 + ); + f = e === i; + } else f = !0; + if (f) + if (void 0 !== t.fallbackVersion) { + const e = i; + if ('string' != typeof t.fallbackVersion) + return ( + (v.errors = [{ params: { type: 'string' } }]), !1 + ); + f = e === i; + } else f = !0; + } + } + } + } + l = r === i; } else l = !0; if (l) { - if (void 0 !== e.request) { - let t = e.request; - const r = i; - if (i === r) { - if ('string' != typeof t) - return (b.errors = [{ params: { type: 'string' } }]), !1; - if (t.length < 1) return (b.errors = [{ params: {} }]), !1; + if (void 0 !== e.include) { + let t = e.include; + const r = i, + n = i, + s = i; + let o = !1; + const p = i; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if (void 0 === t.request && (e = 'request')) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; + } + } + var y = p === i; + if (((o = o || y), !o)) { + const e = i; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if (void 0 === t.version && (e = 'version')) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; + } + } + if (((y = e === i), (o = o || y), !o)) { + const e = i; + if (t && 'object' == typeof t && !Array.isArray(t)) { + let e; + if ( + void 0 === t.fallbackVersion && + (e = 'fallbackVersion') + ) { + const t = { params: { missingProperty: e } }; + null === a ? (a = [t]) : a.push(t), i++; + } + } + (y = e === i), (o = o || y); + } + } + if (!o) { + const e = { params: {} }; + return ( + null === a ? (a = [e]) : a.push(e), i++, (v.errors = a), !1 + ); + } + if ( + ((i = s), + null !== a && (s ? (a.length = s) : (a = null)), + i === n) + ) { + if (!t || 'object' != typeof t || Array.isArray(t)) + return (v.errors = [{ params: { type: 'object' } }]), !1; + { + const e = i; + for (const e in t) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) + return ( + (v.errors = [{ params: { additionalProperty: e } }]), !1 + ); + if (e === i) { + if (void 0 !== t.request) { + let e = t.request; + const r = i; + if ( + 'string' != typeof e && + (!e || 'object' != typeof e || Array.isArray(e)) + ) + return ( + (v.errors = [ + { params: { type: b.properties.request.type } }, + ]), + !1 + ); + var c = r === i; + } else c = !0; + if (c) { + if (void 0 !== t.version) { + const e = i; + if ('string' != typeof t.version) + return ( + (v.errors = [{ params: { type: 'string' } }]), !1 + ); + c = e === i; + } else c = !0; + if (c) + if (void 0 !== t.fallbackVersion) { + const e = i; + if ('string' != typeof t.fallbackVersion) + return ( + (v.errors = [{ params: { type: 'string' } }]), !1 + ); + c = e === i; + } else c = !0; + } + } + } } l = r === i; } else l = !0; if (l) { - if (void 0 !== e.layer) { - let t = e.layer; - const r = i; - if (i === r) { - if ('string' != typeof t) - return (b.errors = [{ params: { type: 'string' } }]), !1; - if (t.length < 1) return (b.errors = [{ params: {} }]), !1; + if (void 0 !== e.import) { + let t = e.import; + const r = i, + n = i; + let s = !1; + const o = i; + if (!1 !== t) { + const e = { + params: { + allowedValues: h.properties.import.anyOf[0].enum, + }, + }; + null === a ? (a = [e]) : a.push(e), i++; + } + var u = o === i; + if (((s = s || u), !s)) { + const e = i; + if (i == i) + if ('string' == typeof t) { + if (t.length < 1) { + const e = { params: {} }; + null === a ? (a = [e]) : a.push(e), i++; + } + } else { + const e = { params: { type: 'string' } }; + null === a ? (a = [e]) : a.push(e), i++; + } + (u = e === i), (s = s || u); + } + if (!s) { + const e = { params: {} }; + return ( + null === a ? (a = [e]) : a.push(e), i++, (v.errors = a), !1 + ); } - l = r === i; + (i = n), + null !== a && (n ? (a.length = n) : (a = null)), + (l = r === i); } else l = !0; if (l) { - if (void 0 !== e.issuerLayer) { - let t = e.issuerLayer; + if (void 0 !== e.request) { + let t = e.request; const r = i; if (i === r) { if ('string' != typeof t) - return (b.errors = [{ params: { type: 'string' } }]), !1; - if (t.length < 1) return (b.errors = [{ params: {} }]), !1; + return (v.errors = [{ params: { type: 'string' } }]), !1; + if (t.length < 1) return (v.errors = [{ params: {} }]), !1; } l = r === i; } else l = !0; if (l) { - if (void 0 !== e.packageName) { - let t = e.packageName; + if (void 0 !== e.layer) { + let t = e.layer; const r = i; if (i === r) { if ('string' != typeof t) return ( - (b.errors = [{ params: { type: 'string' } }]), !1 + (v.errors = [{ params: { type: 'string' } }]), !1 ); if (t.length < 1) - return (b.errors = [{ params: {} }]), !1; + return (v.errors = [{ params: {} }]), !1; } l = r === i; } else l = !0; if (l) { - if (void 0 !== e.requiredVersion) { - let t = e.requiredVersion; - const r = i, - n = i; - let s = !1; - const o = i; - if (!1 !== t) { - const e = { - params: { - allowedValues: - h.properties.requiredVersion.anyOf[0].enum, - }, - }; - null === a ? (a = [e]) : a.push(e), i++; - } - var f = o === i; - if (((s = s || f), !s)) { - const e = i; - if ('string' != typeof t) { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), i++; - } - (f = e === i), (s = s || f); - } - if (!s) { - const e = { params: {} }; - return ( - null === a ? (a = [e]) : a.push(e), - i++, - (b.errors = a), - !1 - ); + if (void 0 !== e.issuerLayer) { + let t = e.issuerLayer; + const r = i; + if (i === r) { + if ('string' != typeof t) + return ( + (v.errors = [{ params: { type: 'string' } }]), !1 + ); + if (t.length < 1) + return (v.errors = [{ params: {} }]), !1; } - (i = n), - null !== a && (n ? (a.length = n) : (a = null)), - (l = r === i); + l = r === i; } else l = !0; if (l) { - if (void 0 !== e.shareKey) { - let t = e.shareKey; + if (void 0 !== e.packageName) { + let t = e.packageName; const r = i; if (i === r) { if ('string' != typeof t) return ( - (b.errors = [{ params: { type: 'string' } }]), !1 + (v.errors = [{ params: { type: 'string' } }]), !1 ); if (t.length < 1) - return (b.errors = [{ params: {} }]), !1; + return (v.errors = [{ params: {} }]), !1; } l = r === i; } else l = !0; if (l) { - if (void 0 !== e.shareScope) { - let t = e.shareScope; + if (void 0 !== e.requiredVersion) { + let t = e.requiredVersion; const r = i, n = i; let s = !1; const o = i; - if (i === o) - if ('string' == typeof t) { - if (t.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), i++; - } - } else { + if (!1 !== t) { + const e = { + params: { + allowedValues: + h.properties.requiredVersion.anyOf[0].enum, + }, + }; + null === a ? (a = [e]) : a.push(e), i++; + } + var m = o === i; + if (((s = s || m), !s)) { + const e = i; + if ('string' != typeof t) { const e = { params: { type: 'string' } }; null === a ? (a = [e]) : a.push(e), i++; } - var y = o === i; - if (((s = s || y), !s)) { - const e = i; - if (i === e) - if (Array.isArray(t)) { - const e = t.length; - for (let r = 0; r < e; r++) { - let e = t[r]; - const n = i; - if (i === n) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), i++; - } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), i++; - } - if (n !== i) break; - } - } else { - const e = { params: { type: 'array' } }; - null === a ? (a = [e]) : a.push(e), i++; - } - (y = e === i), (s = s || y); + (m = e === i), (s = s || m); } if (!s) { const e = { params: {} }; return ( null === a ? (a = [e]) : a.push(e), i++, - (b.errors = a), + (v.errors = a), !1 ); } @@ -1677,66 +1862,167 @@ function b( (l = r === i); } else l = !0; if (l) { - if (void 0 !== e.singleton) { - const t = i; - if ('boolean' != typeof e.singleton) - return ( - (b.errors = [{ params: { type: 'boolean' } }]), - !1 - ); - l = t === i; - } else l = !0; - if (l) { - if (void 0 !== e.strictVersion) { - const t = i; - if ('boolean' != typeof e.strictVersion) + if (void 0 !== e.shareKey) { + let t = e.shareKey; + const r = i; + if (i === r) { + if ('string' != typeof t) return ( - (b.errors = [ - { params: { type: 'boolean' } }, - ]), + (v.errors = [{ params: { type: 'string' } }]), !1 ); - l = t === i; - } else l = !0; - if (l) - if (void 0 !== e.version) { - let t = e.version; - const r = i, - n = i; - let s = !1; - const o = i; - if (!1 !== t) { - const e = { - params: { - allowedValues: - h.properties.version.anyOf[0].enum, - }, - }; + if (t.length < 1) + return (v.errors = [{ params: {} }]), !1; + } + l = r === i; + } else l = !0; + if (l) { + if (void 0 !== e.shareScope) { + let t = e.shareScope; + const r = i, + n = i; + let s = !1; + const o = i; + if (i === o) + if ('string' == typeof t) { + if (t.length < 1) { + const e = { params: {} }; + null === a ? (a = [e]) : a.push(e), i++; + } + } else { + const e = { params: { type: 'string' } }; null === a ? (a = [e]) : a.push(e), i++; } - var c = o === i; - if (((s = s || c), !s)) { - const e = i; - if ('string' != typeof t) { - const e = { params: { type: 'string' } }; + var d = o === i; + if (((s = s || d), !s)) { + const e = i; + if (i === e) + if (Array.isArray(t)) { + const e = t.length; + for (let r = 0; r < e; r++) { + let e = t[r]; + const n = i; + if (i === n) + if ('string' == typeof e) { + if (e.length < 1) { + const e = { params: {} }; + null === a ? (a = [e]) : a.push(e), + i++; + } + } else { + const e = { + params: { type: 'string' }, + }; + null === a ? (a = [e]) : a.push(e), + i++; + } + if (n !== i) break; + } + } else { + const e = { params: { type: 'array' } }; null === a ? (a = [e]) : a.push(e), i++; } - (c = e === i), (s = s || c); - } - if (!s) { - const e = { params: {} }; + (d = e === i), (s = s || d); + } + if (!s) { + const e = { params: {} }; + return ( + null === a ? (a = [e]) : a.push(e), + i++, + (v.errors = a), + !1 + ); + } + (i = n), + null !== a && (n ? (a.length = n) : (a = null)), + (l = r === i); + } else l = !0; + if (l) { + if (void 0 !== e.singleton) { + const t = i; + if ('boolean' != typeof e.singleton) return ( - null === a ? (a = [e]) : a.push(e), - i++, - (b.errors = a), + (v.errors = [ + { params: { type: 'boolean' } }, + ]), !1 ); - } - (i = n), - null !== a && - (n ? (a.length = n) : (a = null)), - (l = r === i); + l = t === i; } else l = !0; + if (l) { + if (void 0 !== e.strictVersion) { + const t = i; + if ('boolean' != typeof e.strictVersion) + return ( + (v.errors = [ + { params: { type: 'boolean' } }, + ]), + !1 + ); + l = t === i; + } else l = !0; + if (l) { + if (void 0 !== e.version) { + let t = e.version; + const r = i, + n = i; + let s = !1; + const o = i; + if (!1 !== t) { + const e = { + params: { + allowedValues: + h.properties.version.anyOf[0].enum, + }, + }; + null === a ? (a = [e]) : a.push(e), i++; + } + var g = o === i; + if (((s = s || g), !s)) { + const e = i; + if ('string' != typeof t) { + const e = { + params: { type: 'string' }, + }; + null === a ? (a = [e]) : a.push(e), i++; + } + (g = e === i), (s = s || g); + } + if (!s) { + const e = { params: {} }; + return ( + null === a ? (a = [e]) : a.push(e), + i++, + (v.errors = a), + !1 + ); + } + (i = n), + null !== a && + (n ? (a.length = n) : (a = null)), + (l = r === i); + } else l = !0; + if (l) + if ( + void 0 !== + e.nodeModulesReconstructedLookup + ) { + const t = i; + if ( + 'boolean' != + typeof e.nodeModulesReconstructedLookup + ) + return ( + (v.errors = [ + { params: { type: 'boolean' } }, + ]), + !1 + ); + l = t === i; + } else l = !0; + } + } + } } } } @@ -1750,9 +2036,9 @@ function b( } } } - return (b.errors = a), 0 === i; + return (v.errors = a), 0 === i; } -function v( +function P( e, { instancePath: t = '', @@ -1765,19 +2051,19 @@ function v( a = 0; if (0 === a) { if (!e || 'object' != typeof e || Array.isArray(e)) - return (v.errors = [{ params: { type: 'object' } }]), !1; + return (P.errors = [{ params: { type: 'object' } }]), !1; for (const r in e) { let n = e[r]; const l = a, p = a; let f = !1; const y = a; - b(n, { + v(n, { instancePath: t + '/' + r.replace(/~/g, '~0').replace(/\//g, '~1'), parentData: e, parentDataProperty: r, rootData: s, - }) || ((o = null === o ? b.errors : o.concat(b.errors)), (a = o.length)); + }) || ((o = null === o ? v.errors : o.concat(v.errors)), (a = o.length)); var i = y === a; if (((f = f || i), !f)) { const e = a; @@ -1795,15 +2081,15 @@ function v( } if (!f) { const e = { params: {} }; - return null === o ? (o = [e]) : o.push(e), a++, (v.errors = o), !1; + return null === o ? (o = [e]) : o.push(e), a++, (P.errors = o), !1; } if (((a = p), null !== o && (p ? (o.length = p) : (o = null)), l !== a)) break; } } - return (v.errors = o), 0 === a; + return (P.errors = o), 0 === a; } -function P( +function j( e, { instancePath: t = '', @@ -1839,13 +2125,13 @@ function P( var f = y === a; if (((p = p || f), !p)) { const i = a; - v(r, { + P(r, { instancePath: t + '/' + n, parentData: e, parentDataProperty: n, rootData: s, }) || - ((o = null === o ? v.errors : o.concat(v.errors)), (a = o.length)), + ((o = null === o ? P.errors : o.concat(P.errors)), (a = o.length)), (f = i === a), (p = p || f); } @@ -1863,23 +2149,23 @@ function P( var y = p === a; if (((l = l || y), !l)) { const i = a; - v(e, { + P(e, { instancePath: t, parentData: r, parentDataProperty: n, rootData: s, - }) || ((o = null === o ? v.errors : o.concat(v.errors)), (a = o.length)), + }) || ((o = null === o ? P.errors : o.concat(P.errors)), (a = o.length)), (y = i === a), (l = l || y); } if (!l) { const e = { params: {} }; - return null === o ? (o = [e]) : o.push(e), a++, (P.errors = o), !1; + return null === o ? (o = [e]) : o.push(e), a++, (j.errors = o), !1; } return ( (a = i), null !== o && (i ? (o.length = i) : (o = null)), - (P.errors = o), + (j.errors = o), 0 === a ); } @@ -2144,14 +2430,14 @@ function D( if (m) { if (void 0 !== o.shared) { const e = u; - P(o.shared, { + j(o.shared, { instancePath: a + '/shared', parentData: o, parentDataProperty: 'shared', rootData: f, }) || ((y = - null === y ? P.errors : y.concat(P.errors)), + null === y ? j.errors : y.concat(j.errors)), (u = y.length)), (m = e === u); } else m = !0; @@ -2211,9 +2497,9 @@ function D( : y.push(e), u++; } - var j = e === u; - } else j = !0; - if (j) { + var P = e === u; + } else P = !0; + if (P) { if (void 0 !== r.typesFolder) { const e = u; if ( @@ -2230,9 +2516,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.compiledTypesFolder @@ -2252,9 +2538,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.deleteTypesFolder @@ -2274,9 +2560,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.additionalFilesToCompile @@ -2323,9 +2609,9 @@ function D( : y.push(e), u++; } - j = t === u; - } else j = !0; - if (j) { + P = t === u; + } else P = !0; + if (P) { if ( void 0 !== r.compileInChildProcess @@ -2345,9 +2631,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.compilerInstance @@ -2378,9 +2664,9 @@ function D( : y.push(e), u++; } - j = n === u; - } else j = !0; - if (j) { + P = n === u; + } else P = !0; + if (P) { if ( void 0 !== r.generateAPITypes @@ -2400,9 +2686,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.extractThirdParty @@ -2422,9 +2708,9 @@ function D( : y.push(e), u++; } - j = e === u; - } else j = !0; - if (j) { + P = e === u; + } else P = !0; + if (P) { if ( void 0 !== r.extractRemoteTypes @@ -2448,9 +2734,9 @@ function D( ), u++; } - j = e === u; - } else j = !0; - if (j) + P = e === u; + } else P = !0; + if (P) if ( void 0 !== r.abortOnError @@ -2476,8 +2762,8 @@ function D( ), u++; } - j = e === u; - } else j = !0; + P = e === u; + } else P = !0; } } } @@ -3136,8 +3422,8 @@ function D( null === y ? (y = [e]) : y.push(e), u++; } - var $ = s === u; - if (((n = n || $), !n)) { + var k = s === u; + if (((n = n || k), !n)) { const t = u; if (u === t) if ( @@ -3182,9 +3468,9 @@ function D( : y.push(e), u++; } - var C = t === u; - } else C = !0; - if (C) { + var E = t === u; + } else E = !0; + if (E) { if ( void 0 !== e.disableAssetsAnalyze @@ -3204,9 +3490,9 @@ function D( : y.push(e), u++; } - C = t === u; - } else C = !0; - if (C) { + E = t === u; + } else E = !0; + if (E) { if ( void 0 !== e.fileName ) { @@ -3225,9 +3511,9 @@ function D( : y.push(e), u++; } - C = t === u; - } else C = !0; - if (C) + E = t === u; + } else E = !0; + if (E) if ( void 0 !== e.additionalData @@ -3247,8 +3533,8 @@ function D( : y.push(e), u++; } - C = t === u; - } else C = !0; + E = t === u; + } else E = !0; } } } @@ -3261,7 +3547,7 @@ function D( : y.push(e), u++; } - ($ = t === u), (n = n || $); + (k = t === u), (n = n || k); } if (!n) { const e = { params: {} }; diff --git a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.json b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.json index 314a82c7686..1fee82ec6b6 100644 --- a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.json +++ b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.json @@ -400,6 +400,14 @@ "description": "Include the provided and fallback module directly instead behind an async request. This allows to use this shared module in initial load too. All possible shared modules need to be eager too.", "type": "boolean" }, + "exclude": { + "description": "Options for excluding specific versions or request paths of the shared module. When specified, matching modules will not be shared. Cannot be used with 'include'.", + "$ref": "#/definitions/IncludeExcludeOptions" + }, + "include": { + "description": "Options for including only specific versions or request paths of the shared module. When specified, only matching modules will be shared. Cannot be used with 'exclude'.", + "$ref": "#/definitions/IncludeExcludeOptions" + }, "import": { "description": "Provided module that should be provided to share scope. Also acts as fallback module if no shared module is found in share scope or version isn't valid. Defaults to the property name.", "anyOf": [ @@ -486,6 +494,10 @@ "type": "string" } ] + }, + "nodeModulesReconstructedLookup": { + "description": "Enable reconstructed lookup for node_modules paths for this share item", + "type": "boolean" } } }, @@ -512,6 +524,48 @@ "UmdNamedDefine": { "description": "If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.", "type": "boolean" + }, + "IncludeExcludeOptions": { + "type": "object", + "properties": { + "request": { + "type": ["string", "object"], + "description": "A string (which can be a regex pattern) or a RegExp object to match the request path." + }, + "version": { + "type": "string", + "description": "Semantic versioning range to match against the module's version." + }, + "fallbackVersion": { + "type": "string", + "description": "Semantic versioning range to match against the fallback module's version for exclusion/inclusion context where applicable." + } + }, + "additionalProperties": false, + "anyOf": [ + { "required": ["request"] }, + { "required": ["version"] }, + { "required": ["fallbackVersion"] } + ] + }, + "Exclude": { + "description": "Advanced filtering options.", + "type": "object", + "additionalProperties": false, + "properties": { + "request": { + "description": "Regular expression pattern to filter module requests", + "instanceof": "RegExp" + }, + "version": { + "description": "Specific version string or range to filter by (exclude matches).", + "type": "string" + }, + "fallbackVersion": { + "description": "Optional specific version string to check against the filter.version range instead of reading package.json.", + "type": "string" + } + } } }, "title": "ModuleFederationPluginOptions", diff --git a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.ts b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.ts index 01b00a96b10..fa6bdd1602c 100644 --- a/packages/enhanced/src/schemas/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/schemas/container/ModuleFederationPlugin.ts @@ -434,6 +434,16 @@ export default { 'Include the provided and fallback module directly instead behind an async request. This allows to use this shared module in initial load too. All possible shared modules need to be eager too.', type: 'boolean', }, + exclude: { + description: + "Options for excluding specific versions or request paths of the shared module. When specified, matching modules will not be shared. Cannot be used with 'include'.", + $ref: '#/definitions/IncludeExcludeOptions', + }, + include: { + description: + "Options for including only specific versions or request paths of the shared module. When specified, only matching modules will be shared. Cannot be used with 'exclude'.", + $ref: '#/definitions/IncludeExcludeOptions', + }, import: { description: "Provided module that should be provided to share scope. Also acts as fallback module if no shared module is found in share scope or version isn't valid. Defaults to the property name.", @@ -529,6 +539,11 @@ export default { }, ], }, + nodeModulesReconstructedLookup: { + description: + 'Enable reconstructed lookup for node_modules paths for this share item', + type: 'boolean', + }, }, }, SharedItem: { @@ -557,6 +572,59 @@ export default { 'If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.', type: 'boolean', }, + IncludeExcludeOptions: { + type: 'object', + properties: { + request: { + type: ['string', 'object'], + description: + 'A string (which can be a regex pattern) or a RegExp object to match the request path.', + }, + version: { + type: 'string', + description: + "Semantic versioning range to match against the module's version.", + }, + fallbackVersion: { + type: 'string', + description: + "Semantic versioning range to match against the fallback module's version for exclusion/inclusion context where applicable.", + }, + }, + additionalProperties: false, + anyOf: [ + { + required: ['request'], + }, + { + required: ['version'], + }, + { + required: ['fallbackVersion'], + }, + ], + }, + Exclude: { + description: 'Advanced filtering options.', + type: 'object', + additionalProperties: false, + properties: { + request: { + description: 'Regular expression pattern to filter module requests', + instanceof: 'RegExp', + }, + version: { + description: + 'Specific version string or range to filter by (exclude matches).', + type: 'string', + }, + fallbackVersion: { + description: + 'Optional specific version string to check against the filter.version range instead of reading package.json.', + type: 'string', + }, + }, + }, }, title: 'ModuleFederationPluginOptions', type: 'object', diff --git a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.check.ts b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.check.ts index 6ff072df881..506aab0ac50 100644 --- a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.check.ts +++ b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.check.ts @@ -28,22 +28,9 @@ const r = { request: { type: 'string', minLength: 1 }, singleton: { type: 'boolean' }, strictVersion: { type: 'boolean' }, - include: { - type: 'object', - additionalProperties: !1, - properties: { - version: { type: 'string' }, - request: { anyOf: [{ type: 'string' }, { instanceof: 'RegExp' }] }, - }, - }, - exclude: { - type: 'object', - additionalProperties: !1, - properties: { - version: { type: 'string' }, - request: { anyOf: [{ type: 'string' }, { instanceof: 'RegExp' }] }, - }, - }, + exclude: { $ref: '#/definitions/IncludeExcludeOptions' }, + include: { $ref: '#/definitions/IncludeExcludeOptions' }, + nodeModulesReconstructedLookup: { type: 'boolean' }, }, }, e = Object.prototype.hasOwnProperty; @@ -290,10 +277,10 @@ function t( f = r === p; } else f = !0; if (f) { - if (void 0 !== s.include) { - let r = s.include; + if (void 0 !== s.exclude) { + let r = s.exclude; const e = p; - if (p === e) { + if (p == p) { if ( !r || 'object' != typeof r || @@ -308,7 +295,11 @@ function t( { const e = p; for (const e in r) - if ('version' !== e && 'request' !== e) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) return ( (t.errors = [ { @@ -318,69 +309,83 @@ function t( !1 ); if (e === p) { - if (void 0 !== r.version) { - const e = p; - if ('string' != typeof r.version) + if (void 0 !== r.request) { + let e = r.request; + const s = p, + n = p; + let o = !1; + const a = p; + if ('string' != typeof e) { + const r = { + params: { type: 'string' }, + }; + null === l ? (l = [r]) : l.push(r), + p++; + } + var m = a === p; + if (((o = o || m), !o)) { + const r = p; + if (!(e instanceof RegExp)) { + const r = { params: {} }; + null === l ? (l = [r]) : l.push(r), + p++; + } + (m = r === p), (o = o || m); + } + if (!o) { + const r = { params: {} }; return ( - (t.errors = [ - { params: { type: 'string' } }, - ]), + null === l ? (l = [r]) : l.push(r), + p++, + (t.errors = l), !1 ); - var g = e === p; + } + (p = n), + null !== l && + (n ? (l.length = n) : (l = null)); + var g = s === p; } else g = !0; - if (g) - if (void 0 !== r.request) { - let e = r.request; - const s = p, - n = p; - let o = !1; - const a = p; - if ('string' != typeof e) { - const r = { - params: { type: 'string' }, - }; - null === l ? (l = [r]) : l.push(r), - p++; - } - var m = a === p; - if (((o = o || m), !o)) { - const r = p; - if (!(e instanceof RegExp)) { - const r = { params: {} }; - null === l - ? (l = [r]) - : l.push(r), - p++; - } - (m = r === p), (o = o || m); - } - if (!o) { - const r = { params: {} }; + if (g) { + if (void 0 !== r.version) { + const e = p; + if ('string' != typeof r.version) return ( - null === l - ? (l = [r]) - : l.push(r), - p++, - (t.errors = l), + (t.errors = [ + { params: { type: 'string' } }, + ]), !1 ); - } - (p = n), - null !== l && - (n ? (l.length = n) : (l = null)), - (g = s === p); + g = e === p; } else g = !0; + if (g) + if (void 0 !== r.fallbackVersion) { + const e = p; + if ( + 'string' != + typeof r.fallbackVersion + ) + return ( + (t.errors = [ + { + params: { type: 'string' }, + }, + ]), + !1 + ); + g = e === p; + } else g = !0; + } } } } f = e === p; } else f = !0; - if (f) - if (void 0 !== s.exclude) { - let r = s.exclude; + if (f) { + if (void 0 !== s.include) { + let r = s.include; const e = p; - if (p === e) { + if (p == p) { if ( !r || 'object' != typeof r || @@ -395,7 +400,11 @@ function t( { const e = p; for (const e in r) - if ('version' !== e && 'request' !== e) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) return ( (t.errors = [ { @@ -407,68 +416,104 @@ function t( !1 ); if (e === p) { - if (void 0 !== r.version) { - const e = p; - if ('string' != typeof r.version) - return ( - (t.errors = [ - { params: { type: 'string' } }, - ]), - !1 - ); - var h = e === p; - } else h = !0; - if (h) - if (void 0 !== r.request) { - let e = r.request; - const s = p, - n = p; - let o = !1; - const a = p; - if ('string' != typeof e) { - const r = { - params: { type: 'string' }, - }; + if (void 0 !== r.request) { + let e = r.request; + const s = p, + n = p; + let o = !1; + const a = p; + if ('string' != typeof e) { + const r = { + params: { type: 'string' }, + }; + null === l ? (l = [r]) : l.push(r), + p++; + } + var h = a === p; + if (((o = o || h), !o)) { + const r = p; + if (!(e instanceof RegExp)) { + const r = { params: {} }; null === l ? (l = [r]) : l.push(r), p++; } - var d = a === p; - if (((o = o || d), !o)) { - const r = p; - if (!(e instanceof RegExp)) { - const r = { params: {} }; - null === l - ? (l = [r]) - : l.push(r), - p++; - } - (d = r === p), (o = o || d); - } - if (!o) { - const r = { params: {} }; + (h = r === p), (o = o || h); + } + if (!o) { + const r = { params: {} }; + return ( + null === l + ? (l = [r]) + : l.push(r), + p++, + (t.errors = l), + !1 + ); + } + (p = n), + null !== l && + (n ? (l.length = n) : (l = null)); + var d = s === p; + } else d = !0; + if (d) { + if (void 0 !== r.version) { + const e = p; + if ('string' != typeof r.version) return ( - null === l - ? (l = [r]) - : l.push(r), - p++, - (t.errors = l), + (t.errors = [ + { + params: { type: 'string' }, + }, + ]), !1 ); - } - (p = n), - null !== l && - (n - ? (l.length = n) - : (l = null)), - (h = s === p); - } else h = !0; + d = e === p; + } else d = !0; + if (d) + if (void 0 !== r.fallbackVersion) { + const e = p; + if ( + 'string' != + typeof r.fallbackVersion + ) + return ( + (t.errors = [ + { + params: { + type: 'string', + }, + }, + ]), + !1 + ); + d = e === p; + } else d = !0; + } } } } f = e === p; } else f = !0; + if (f) + if ( + void 0 !== s.nodeModulesReconstructedLookup + ) { + const r = p; + if ( + 'boolean' != + typeof s.nodeModulesReconstructedLookup + ) + return ( + (t.errors = [ + { params: { type: 'boolean' } }, + ]), + !1 + ); + f = r === p; + } else f = !0; + } } } } @@ -637,7 +682,7 @@ function o( { const t = l; for (const e in r) - if ('consumes' !== e && 'shareScope' !== e) + if ('consumes' !== e && 'shareScope' !== e && 'experiments' !== e) return (o.errors = [{ params: { additionalProperty: e } }]), !1; if (t === l) { if (void 0 !== r.consumes) { @@ -652,7 +697,7 @@ function o( (l = i.length)); var p = t === l; } else p = !0; - if (p) + if (p) { if (void 0 !== r.shareScope) { let e = r.shareScope; const t = l, @@ -706,6 +751,32 @@ function o( null !== i && (s ? (i.length = s) : (i = null)), (p = t === l); } else p = !0; + if (p) + if (void 0 !== r.experiments) { + let e = r.experiments; + const t = l; + if (l === t) { + if (!e || 'object' != typeof e || Array.isArray(e)) + return (o.errors = [{ params: { type: 'object' } }]), !1; + { + const r = l; + for (const r in e) + if ('nodeModulesReconstructedLookup' !== r) + return ( + (o.errors = [{ params: { additionalProperty: r } }]), + !1 + ); + if ( + r === l && + void 0 !== e.nodeModulesReconstructedLookup && + 'boolean' != typeof e.nodeModulesReconstructedLookup + ) + return (o.errors = [{ params: { type: 'boolean' } }]), !1; + } + } + p = t === l; + } else p = !0; + } } } } diff --git a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.json b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.json index 0c15b4f551e..8359703b42f 100644 --- a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.json +++ b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.json @@ -105,49 +105,17 @@ "description": "Do not accept shared module if version is not valid (defaults to yes, if local fallback module is available and shared module is not a singleton, otherwise no, has no effect if there is no required version specified).", "type": "boolean" }, + "exclude": { + "description": "Filter consumed modules based on the request path.", + "$ref": "#/definitions/IncludeExcludeOptions" + }, "include": { - "description": "Include filters for consuming shared modules.", - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "description": "Version requirement that must be satisfied for the shared module to be included.", - "type": "string" - }, - "request": { - "description": "Request pattern that must match for the shared module to be included.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "RegExp" - } - ] - } - } + "description": "Filter consumed modules based on the request path (only include matches).", + "$ref": "#/definitions/IncludeExcludeOptions" }, - "exclude": { - "description": "Exclude filters for consuming shared modules.", - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "description": "Version requirement that if satisfied will exclude the shared module.", - "type": "string" - }, - "request": { - "description": "Request pattern that if matched will exclude the shared module.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "RegExp" - } - ] - } - } + "nodeModulesReconstructedLookup": { + "description": "Enable reconstructed lookup for node_modules paths for this share item", + "type": "boolean" } } }, @@ -170,6 +138,51 @@ } ] } + }, + "Exclude": { + "description": "Advanced filtering options.", + "type": "object", + "additionalProperties": false, + "properties": { + "request": { + "description": "Regular expression pattern to filter module requests", + "instanceof": "RegExp" + }, + "version": { + "description": "Specific version string or range to filter by (exclude matches).", + "type": "string" + }, + "fallbackVersion": { + "description": "Optional specific version string to check against the filter.version range instead of reading package.json.", + "type": "string" + } + } + }, + "IncludeExcludeOptions": { + "type": "object", + "properties": { + "request": { + "anyOf": [ + { + "type": "string", + "description": "Request string to match exactly." + }, + { + "instanceof": "RegExp", + "description": "Regular expression to match the request path." + } + ] + }, + "version": { + "type": "string", + "description": "Semantic versioning range to match against the module's version." + }, + "fallbackVersion": { + "type": "string", + "description": "Optional specific version string to check against the version range instead of reading package.json." + } + }, + "additionalProperties": false } }, "title": "ConsumeSharedPluginOptions", @@ -195,6 +208,17 @@ } } ] + }, + "experiments": { + "description": "Experimental features configuration", + "type": "object", + "additionalProperties": false, + "properties": { + "nodeModulesReconstructedLookup": { + "description": "Enable reconstructed lookup for node_modules paths", + "type": "boolean" + } + } } }, "required": ["consumes"] diff --git a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.ts b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.ts index e180bc52ce9..cf7fad3b09a 100644 --- a/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.ts +++ b/packages/enhanced/src/schemas/sharing/ConsumeSharedPlugin.ts @@ -121,53 +121,19 @@ export default { 'Do not accept shared module if version is not valid (defaults to yes, if local fallback module is available and shared module is not a singleton, otherwise no, has no effect if there is no required version specified).', type: 'boolean', }, + exclude: { + description: 'Filter consumed modules based on the request path.', + $ref: '#/definitions/IncludeExcludeOptions', + }, include: { - description: 'Include filters for consuming shared modules.', - type: 'object', - additionalProperties: false, - properties: { - version: { - description: - 'Version requirement that must be satisfied for the shared module to be included.', - type: 'string', - }, - request: { - description: - 'Request pattern that must match for the shared module to be included.', - anyOf: [ - { - type: 'string', - }, - { - instanceof: 'RegExp', - }, - ], - }, - }, + description: + 'Filter consumed modules based on the request path (only include matches).', + $ref: '#/definitions/IncludeExcludeOptions', }, - exclude: { - description: 'Exclude filters for consuming shared modules.', - type: 'object', - additionalProperties: false, - properties: { - version: { - description: - 'Version requirement that if satisfied will exclude the shared module.', - type: 'string', - }, - request: { - description: - 'Request pattern that if matched will exclude the shared module.', - anyOf: [ - { - type: 'string', - }, - { - instanceof: 'RegExp', - }, - ], - }, - }, + nodeModulesReconstructedLookup: { + description: + 'Enable reconstructed lookup for node_modules paths for this share item', + type: 'boolean', }, }, }, @@ -192,6 +158,55 @@ export default { ], }, }, + Exclude: { + description: 'Advanced filtering options.', + type: 'object', + additionalProperties: false, + properties: { + request: { + description: 'Regular expression pattern to filter module requests', + instanceof: 'RegExp', + }, + version: { + description: + 'Specific version string or range to filter by (exclude matches).', + type: 'string', + }, + fallbackVersion: { + description: + 'Optional specific version string to check against the filter.version range instead of reading package.json.', + type: 'string', + }, + }, + }, + IncludeExcludeOptions: { + type: 'object', + properties: { + request: { + anyOf: [ + { + type: 'string', + description: 'Request string to match exactly.', + }, + { + instanceof: 'RegExp', + description: 'Regular expression to match the request path.', + }, + ], + }, + version: { + type: 'string', + description: + "Semantic versioning range to match against the module's version.", + }, + fallbackVersion: { + type: 'string', + description: + 'Optional specific version string to check against the version range instead of reading package.json.', + }, + }, + additionalProperties: false, + }, }, title: 'ConsumeSharedPluginOptions', description: 'Options for consuming shared modules.', @@ -218,6 +233,17 @@ export default { }, ], }, + experiments: { + description: 'Experimental features configuration', + type: 'object', + additionalProperties: false, + properties: { + nodeModulesReconstructedLookup: { + description: 'Enable reconstructed lookup for node_modules paths', + type: 'boolean', + }, + }, + }, }, required: ['consumes'], } as const; diff --git a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.check.ts b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.check.ts index 42203cd17b4..4b97867c6a2 100644 --- a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.check.ts +++ b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.check.ts @@ -4,9 +4,9 @@ * This file was automatically generated. * DO NOT MODIFY BY HAND. */ -export const validate = r; -export default r; -const e = { +export const validate = o; +export default o; +const r = { type: 'object', additionalProperties: !1, properties: { @@ -25,441 +25,480 @@ const e = { layer: { type: 'string', minLength: 1 }, issuerLayer: { type: 'string', minLength: 1 }, version: { anyOf: [{ enum: [!1] }, { type: 'string' }] }, - include: { - type: 'object', - additionalProperties: !1, - properties: { - version: { type: 'string' }, - request: { anyOf: [{ type: 'string' }, { instanceof: 'RegExp' }] }, - }, - }, - exclude: { - type: 'object', - additionalProperties: !1, - properties: { - version: { type: 'string' }, - request: { anyOf: [{ type: 'string' }, { instanceof: 'RegExp' }] }, - }, - }, + exclude: { $ref: '#/definitions/Exclude' }, + include: { $ref: '#/definitions/IncludeExcludeOptions' }, + nodeModulesReconstructedLookup: { type: 'boolean' }, }, }, - t = Object.prototype.hasOwnProperty; -function s( - n, + e = Object.prototype.hasOwnProperty; +function t( + s, { - instancePath: r = '', + instancePath: n = '', parentData: o, - parentDataProperty: i, - rootData: l = n, + parentDataProperty: a, + rootData: i = s, } = {}, ) { - let a = null, + let l = null, p = 0; if (0 === p) { - if (!n || 'object' != typeof n || Array.isArray(n)) - return (s.errors = [{ params: { type: 'object' } }]), !1; - for (const r in n) { - let o = n[r]; - const i = p, - l = p; - let b = !1; - const P = p; - if (p == p) - if (o && 'object' == typeof o && !Array.isArray(o)) { - const s = p; - for (const s in o) - if (!t.call(e.properties, s)) { - const e = { params: { additionalProperty: s } }; - null === a ? (a = [e]) : a.push(e), p++; - break; + if (!s || 'object' != typeof s || Array.isArray(s)) + return (t.errors = [{ params: { type: 'object' } }]), !1; + { + const n = p; + for (const n in s) + if (!e.call(r.properties, n)) + return (t.errors = [{ params: { additionalProperty: n } }]), !1; + if (n === p) { + if (void 0 !== s.eager) { + const r = p; + if ('boolean' != typeof s.eager) + return (t.errors = [{ params: { type: 'boolean' } }]), !1; + var f = r === p; + } else f = !0; + if (f) { + if (void 0 !== s.shareKey) { + let r = s.shareKey; + const e = p; + if (p === e) { + if ('string' != typeof r) + return (t.errors = [{ params: { type: 'string' } }]), !1; + if (r.length < 1) return (t.errors = [{ params: {} }]), !1; } - if (s === p) { - if (void 0 !== o.eager) { + f = e === p; + } else f = !0; + if (f) { + if (void 0 !== s.request) { + let r = s.request; const e = p; - if ('boolean' != typeof o.eager) { - const e = { params: { type: 'boolean' } }; - null === a ? (a = [e]) : a.push(e), p++; + if (p === e) { + if ('string' != typeof r) + return (t.errors = [{ params: { type: 'string' } }]), !1; + if (r.length < 1) return (t.errors = [{ params: {} }]), !1; } - var u = e === p; - } else u = !0; - if (u) { - if (void 0 !== o.shareKey) { - let e = o.shareKey; - const t = p; - if (p === t) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; + f = e === p; + } else f = !0; + if (f) { + if (void 0 !== s.shareScope) { + let r = s.shareScope; + const e = p, + n = p; + let o = !1; + const a = p; + if (p === a) + if ('string' == typeof r) { + if (r.length < 1) { + const r = { params: {} }; + null === l ? (l = [r]) : l.push(r), p++; } } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; + const r = { params: { type: 'string' } }; + null === l ? (l = [r]) : l.push(r), p++; } - u = t === p; - } else u = !0; - if (u) { - if (void 0 !== o.request) { - let e = o.request; - const t = p; - if (p === t) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; + var u = a === p; + if (((o = o || u), !o)) { + const e = p; + if (p === e) + if (Array.isArray(r)) { + const e = r.length; + for (let t = 0; t < e; t++) { + let e = r[t]; + const s = p; + if (p === s) + if ('string' == typeof e) { + if (e.length < 1) { + const r = { params: {} }; + null === l ? (l = [r]) : l.push(r), p++; + } + } else { + const r = { params: { type: 'string' } }; + null === l ? (l = [r]) : l.push(r), p++; + } + if (s !== p) break; } } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; + const r = { params: { type: 'array' } }; + null === l ? (l = [r]) : l.push(r), p++; } - u = t === p; - } else u = !0; - if (u) { - if (void 0 !== o.shareScope) { - let e = o.shareScope; - const t = p, - s = p; - let n = !1; + (u = e === p), (o = o || u); + } + if (!o) { + const r = { params: {} }; + return ( + null === l ? (l = [r]) : l.push(r), p++, (t.errors = l), !1 + ); + } + (p = n), + null !== l && (n ? (l.length = n) : (l = null)), + (f = e === p); + } else f = !0; + if (f) { + if (void 0 !== s.requiredVersion) { + let e = s.requiredVersion; + const n = p, + o = p; + let a = !1; + const i = p; + if (!1 !== e) { + const e = { + params: { + allowedValues: + r.properties.requiredVersion.anyOf[0].enum, + }, + }; + null === l ? (l = [e]) : l.push(e), p++; + } + var c = i === p; + if (((a = a || c), !a)) { const r = p; - if (p === r) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; - } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; - } - var f = r === p; - if (((n = n || f), !n)) { - const t = p; - if (p === t) - if (Array.isArray(e)) { - const t = e.length; - for (let s = 0; s < t; s++) { - let t = e[s]; - const n = p; - if (p === n) - if ('string' == typeof t) { - if (t.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; - } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; - } - if (n !== p) break; - } - } else { - const e = { params: { type: 'array' } }; - null === a ? (a = [e]) : a.push(e), p++; - } - (f = t === p), (n = n || f); + if ('string' != typeof e) { + const r = { params: { type: 'string' } }; + null === l ? (l = [r]) : l.push(r), p++; } - if (n) - (p = s), null !== a && (s ? (a.length = s) : (a = null)); - else { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; - } - u = t === p; - } else u = !0; - if (u) { - if (void 0 !== o.requiredVersion) { - let t = o.requiredVersion; - const s = p, - n = p; - let r = !1; - const i = p; - if (!1 !== t) { - const t = { - params: { - allowedValues: - e.properties.requiredVersion.anyOf[0].enum, - }, - }; - null === a ? (a = [t]) : a.push(t), p++; - } - var c = i === p; - if (((r = r || c), !r)) { - const e = p; - if ('string' != typeof t) { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; - } - (c = e === p), (r = r || c); - } - if (r) - (p = n), - null !== a && (n ? (a.length = n) : (a = null)); - else { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; - } - u = s === p; - } else u = !0; - if (u) { - if (void 0 !== o.strictVersion) { + (c = r === p), (a = a || c); + } + if (!a) { + const r = { params: {} }; + return ( + null === l ? (l = [r]) : l.push(r), + p++, + (t.errors = l), + !1 + ); + } + (p = o), + null !== l && (o ? (l.length = o) : (l = null)), + (f = n === p); + } else f = !0; + if (f) { + if (void 0 !== s.strictVersion) { + const r = p; + if ('boolean' != typeof s.strictVersion) + return (t.errors = [{ params: { type: 'boolean' } }]), !1; + f = r === p; + } else f = !0; + if (f) { + if (void 0 !== s.singleton) { + const r = p; + if ('boolean' != typeof s.singleton) + return ( + (t.errors = [{ params: { type: 'boolean' } }]), !1 + ); + f = r === p; + } else f = !0; + if (f) { + if (void 0 !== s.layer) { + let r = s.layer; const e = p; - if ('boolean' != typeof o.strictVersion) { - const e = { params: { type: 'boolean' } }; - null === a ? (a = [e]) : a.push(e), p++; + if (p === e) { + if ('string' != typeof r) + return ( + (t.errors = [{ params: { type: 'string' } }]), !1 + ); + if (r.length < 1) + return (t.errors = [{ params: {} }]), !1; } - u = e === p; - } else u = !0; - if (u) { - if (void 0 !== o.singleton) { + f = e === p; + } else f = !0; + if (f) { + if (void 0 !== s.issuerLayer) { + let r = s.issuerLayer; const e = p; - if ('boolean' != typeof o.singleton) { - const e = { params: { type: 'boolean' } }; - null === a ? (a = [e]) : a.push(e), p++; + if (p === e) { + if ('string' != typeof r) + return ( + (t.errors = [{ params: { type: 'string' } }]), + !1 + ); + if (r.length < 1) + return (t.errors = [{ params: {} }]), !1; } - u = e === p; - } else u = !0; - if (u) { - if (void 0 !== o.layer) { - let e = o.layer; - const t = p; - if (p === t) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; - } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; + f = e === p; + } else f = !0; + if (f) { + if (void 0 !== s.version) { + let e = s.version; + const n = p, + o = p; + let a = !1; + const i = p; + if (!1 !== e) { + const e = { + params: { + allowedValues: + r.properties.version.anyOf[0].enum, + }, + }; + null === l ? (l = [e]) : l.push(e), p++; + } + var y = i === p; + if (((a = a || y), !a)) { + const r = p; + if ('string' != typeof e) { + const r = { params: { type: 'string' } }; + null === l ? (l = [r]) : l.push(r), p++; } - u = t === p; - } else u = !0; - if (u) { - if (void 0 !== o.issuerLayer) { - let e = o.issuerLayer; - const t = p; - if (p === t) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; + (y = r === p), (a = a || y); + } + if (!a) { + const r = { params: {} }; + return ( + null === l ? (l = [r]) : l.push(r), + p++, + (t.errors = l), + !1 + ); + } + (p = o), + null !== l && (o ? (l.length = o) : (l = null)), + (f = n === p); + } else f = !0; + if (f) { + if (void 0 !== s.exclude) { + let r = s.exclude; + const e = p; + if (p == p) { + if ( + !r || + 'object' != typeof r || + Array.isArray(r) + ) + return ( + (t.errors = [ + { params: { type: 'object' } }, + ]), + !1 + ); + { + const e = p; + for (const e in r) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) + return ( + (t.errors = [ + { params: { additionalProperty: e } }, + ]), + !1 + ); + if (e === p) { + if (void 0 !== r.request) { + const e = p; + if (!(r.request instanceof RegExp)) + return ( + (t.errors = [{ params: {} }]), !1 + ); + var g = e === p; + } else g = !0; + if (g) { + if (void 0 !== r.version) { + const e = p; + if ('string' != typeof r.version) + return ( + (t.errors = [ + { params: { type: 'string' } }, + ]), + !1 + ); + g = e === p; + } else g = !0; + if (g) + if (void 0 !== r.fallbackVersion) { + const e = p; + if ( + 'string' != typeof r.fallbackVersion + ) + return ( + (t.errors = [ + { params: { type: 'string' } }, + ]), + !1 + ); + g = e === p; + } else g = !0; + } } - } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; } - u = t === p; - } else u = !0; - if (u) { - if (void 0 !== o.version) { - let t = o.version; - const s = p, - n = p; - let r = !1; + } + f = e === p; + } else f = !0; + if (f) { + if (void 0 !== s.include) { + let r = s.include; + const e = p, + n = p, + o = p; + let a = !1; const i = p; - if (!1 !== t) { - const t = { - params: { - allowedValues: - e.properties.version.anyOf[0].enum, - }, - }; - null === a ? (a = [t]) : a.push(t), p++; + if ( + r && + 'object' == typeof r && + !Array.isArray(r) + ) { + let e; + if (void 0 === r.request && (e = 'request')) { + const r = { + params: { missingProperty: e }, + }; + null === l ? (l = [r]) : l.push(r), p++; + } } - var y = i === p; - if (((r = r || y), !r)) { + var d = i === p; + if (((a = a || d), !a)) { const e = p; - if ('string' != typeof t) { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; + if ( + r && + 'object' == typeof r && + !Array.isArray(r) + ) { + let e; + if ( + void 0 === r.version && + (e = 'version') + ) { + const r = { + params: { missingProperty: e }, + }; + null === l ? (l = [r]) : l.push(r), p++; + } } - (y = e === p), (r = r || y); + (d = e === p), (a = a || d); } - if (r) - (p = n), - null !== a && - (n ? (a.length = n) : (a = null)); - else { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; + if (!a) { + const r = { params: {} }; + return ( + null === l ? (l = [r]) : l.push(r), + p++, + (t.errors = l), + !1 + ); } - u = s === p; - } else u = !0; - if (u) { - if (void 0 !== o.include) { - let e = o.include; - const t = p; - if (p === t) - if ( - e && - 'object' == typeof e && - !Array.isArray(e) - ) { - const t = p; - for (const t in e) - if ( - 'version' !== t && - 'request' !== t - ) { - const e = { - params: { additionalProperty: t }, + if ( + ((p = o), + null !== l && + (o ? (l.length = o) : (l = null)), + p === n) + ) { + if ( + !r || + 'object' != typeof r || + Array.isArray(r) + ) + return ( + (t.errors = [ + { params: { type: 'object' } }, + ]), + !1 + ); + { + const e = p; + for (const e in r) + if ( + 'request' !== e && + 'version' !== e && + 'fallbackVersion' !== e + ) + return ( + (t.errors = [ + { + params: { additionalProperty: e }, + }, + ]), + !1 + ); + if (e === p) { + if (void 0 !== r.request) { + let e = r.request; + const s = p, + n = p; + let o = !1; + const a = p; + if ('string' != typeof e) { + const r = { + params: { type: 'string' }, }; - null === a ? (a = [e]) : a.push(e), + null === l ? (l = [r]) : l.push(r), p++; - break; } - if (t === p) { - if (void 0 !== e.version) { - const t = p; - if ('string' != typeof e.version) { - const e = { - params: { type: 'string' }, - }; - null === a ? (a = [e]) : a.push(e), - p++; - } - var h = t === p; - } else h = !0; - if (h) - if (void 0 !== e.request) { - let t = e.request; - const s = p, - n = p; - let r = !1; - const o = p; - if ('string' != typeof t) { - const e = { - params: { type: 'string' }, - }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - var g = o === p; - if (((r = r || g), !r)) { - const e = p; - if (!(t instanceof RegExp)) { - const e = { params: {} }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - (g = e === p), (r = r || g); - } - if (r) - (p = n), - null !== a && - (n - ? (a.length = n) - : (a = null)); - else { - const e = { params: {} }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - h = s === p; - } else h = !0; - } - } else { - const e = { params: { type: 'object' } }; - null === a ? (a = [e]) : a.push(e), p++; - } - u = t === p; - } else u = !0; - if (u) - if (void 0 !== o.exclude) { - let e = o.exclude; - const t = p; - if (p === t) - if ( - e && - 'object' == typeof e && - !Array.isArray(e) - ) { - const t = p; - for (const t in e) - if ( - 'version' !== t && - 'request' !== t - ) { - const e = { - params: { additionalProperty: t }, - }; - null === a ? (a = [e]) : a.push(e), + var h = a === p; + if (((o = o || h), !o)) { + const r = p; + if (!(e instanceof RegExp)) { + const r = { params: {} }; + null === l ? (l = [r]) : l.push(r), p++; - break; } - if (t === p) { - if (void 0 !== e.version) { - const t = p; - if ('string' != typeof e.version) { - const e = { - params: { type: 'string' }, - }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - var m = t === p; - } else m = !0; - if (m) - if (void 0 !== e.request) { - let t = e.request; - const s = p, - n = p; - let r = !1; - const o = p; - if ('string' != typeof t) { - const e = { - params: { type: 'string' }, - }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - var d = o === p; - if (((r = r || d), !r)) { - const e = p; - if (!(t instanceof RegExp)) { - const e = { params: {} }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - (d = e === p), (r = r || d); - } - if (r) - (p = n), - null !== a && - (n - ? (a.length = n) - : (a = null)); - else { - const e = { params: {} }; - null === a - ? (a = [e]) - : a.push(e), - p++; - } - m = s === p; - } else m = !0; + (h = r === p), (o = o || h); } - } else { - const e = { - params: { type: 'object' }, - }; - null === a ? (a = [e]) : a.push(e), p++; + if (!o) { + const r = { params: {} }; + return ( + null === l ? (l = [r]) : l.push(r), + p++, + (t.errors = l), + !1 + ); + } + (p = n), + null !== l && + (n ? (l.length = n) : (l = null)); + var m = s === p; + } else m = !0; + if (m) { + if (void 0 !== r.version) { + const e = p; + if ('string' != typeof r.version) + return ( + (t.errors = [ + { params: { type: 'string' } }, + ]), + !1 + ); + m = e === p; + } else m = !0; + if (m) + if (void 0 !== r.fallbackVersion) { + const e = p; + if ( + 'string' != + typeof r.fallbackVersion + ) + return ( + (t.errors = [ + { + params: { type: 'string' }, + }, + ]), + !1 + ); + m = e === p; + } else m = !0; } - u = t === p; - } else u = !0; - } + } + } + } + f = e === p; + } else f = !0; + if (f) + if ( + void 0 !== s.nodeModulesReconstructedLookup + ) { + const r = p; + if ( + 'boolean' != + typeof s.nodeModulesReconstructedLookup + ) + return ( + (t.errors = [ + { params: { type: 'boolean' } }, + ]), + !1 + ); + f = r === p; + } else f = !0; } } } @@ -470,208 +509,262 @@ function s( } } } - } else { - const e = { params: { type: 'object' } }; - null === a ? (a = [e]) : a.push(e), p++; } - var v = P === p; - if (((b = b || v), !b)) { - const e = p; - if (p == p) + } + } + } + return (t.errors = l), 0 === p; +} +function s( + r, + { + instancePath: e = '', + parentData: n, + parentDataProperty: o, + rootData: a = r, + } = {}, +) { + let i = null, + l = 0; + if (0 === l) { + if (!r || 'object' != typeof r || Array.isArray(r)) + return (s.errors = [{ params: { type: 'object' } }]), !1; + for (const n in r) { + let o = r[n]; + const f = l, + u = l; + let c = !1; + const y = l; + t(o, { + instancePath: e + '/' + n.replace(/~/g, '~0').replace(/\//g, '~1'), + parentData: r, + parentDataProperty: n, + rootData: a, + }) || ((i = null === i ? t.errors : i.concat(t.errors)), (l = i.length)); + var p = y === l; + if (((c = c || p), !c)) { + const r = l; + if (l == l) if ('string' == typeof o) { if (o.length < 1) { - const e = { params: {} }; - null === a ? (a = [e]) : a.push(e), p++; + const r = { params: {} }; + null === i ? (i = [r]) : i.push(r), l++; } } else { - const e = { params: { type: 'string' } }; - null === a ? (a = [e]) : a.push(e), p++; + const r = { params: { type: 'string' } }; + null === i ? (i = [r]) : i.push(r), l++; } - (v = e === p), (b = b || v); + (p = r === l), (c = c || p); } - if (!b) { - const e = { params: {} }; - return null === a ? (a = [e]) : a.push(e), p++, (s.errors = a), !1; + if (!c) { + const r = { params: {} }; + return null === i ? (i = [r]) : i.push(r), l++, (s.errors = i), !1; } - if (((p = l), null !== a && (l ? (a.length = l) : (a = null)), i !== p)) + if (((l = u), null !== i && (u ? (i.length = u) : (i = null)), f !== l)) break; } } - return (s.errors = a), 0 === p; + return (s.errors = i), 0 === l; } function n( - e, + r, { - instancePath: t = '', - parentData: r, + instancePath: e = '', + parentData: t, parentDataProperty: o, - rootData: i = e, + rootData: a = r, } = {}, ) { - let l = null, - a = 0; - const p = a; - let u = !1; - const f = a; - if (a === f) - if (Array.isArray(e)) { - const n = e.length; - for (let r = 0; r < n; r++) { - let n = e[r]; - const o = a, - p = a; - let u = !1; - const f = a; - if (a == a) - if ('string' == typeof n) { - if (n.length < 1) { - const e = { params: {} }; - null === l ? (l = [e]) : l.push(e), a++; + let i = null, + l = 0; + const p = l; + let f = !1; + const u = l; + if (l === u) + if (Array.isArray(r)) { + const t = r.length; + for (let n = 0; n < t; n++) { + let t = r[n]; + const o = l, + p = l; + let f = !1; + const u = l; + if (l == l) + if ('string' == typeof t) { + if (t.length < 1) { + const r = { params: {} }; + null === i ? (i = [r]) : i.push(r), l++; } } else { - const e = { params: { type: 'string' } }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: { type: 'string' } }; + null === i ? (i = [r]) : i.push(r), l++; } - var c = f === a; - if (((u = u || c), !u)) { - const o = a; - s(n, { - instancePath: t + '/' + r, - parentData: e, - parentDataProperty: r, - rootData: i, + var c = u === l; + if (((f = f || c), !f)) { + const o = l; + s(t, { + instancePath: e + '/' + n, + parentData: r, + parentDataProperty: n, + rootData: a, }) || - ((l = null === l ? s.errors : l.concat(s.errors)), (a = l.length)), - (c = o === a), - (u = u || c); + ((i = null === i ? s.errors : i.concat(s.errors)), (l = i.length)), + (c = o === l), + (f = f || c); } - if (u) (a = p), null !== l && (p ? (l.length = p) : (l = null)); + if (f) (l = p), null !== i && (p ? (i.length = p) : (i = null)); else { - const e = { params: {} }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: {} }; + null === i ? (i = [r]) : i.push(r), l++; } - if (o !== a) break; + if (o !== l) break; } } else { - const e = { params: { type: 'array' } }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: { type: 'array' } }; + null === i ? (i = [r]) : i.push(r), l++; } - var y = f === a; - if (((u = u || y), !u)) { - const n = a; - s(e, { - instancePath: t, - parentData: r, + var y = u === l; + if (((f = f || y), !f)) { + const n = l; + s(r, { + instancePath: e, + parentData: t, parentDataProperty: o, - rootData: i, - }) || ((l = null === l ? s.errors : l.concat(s.errors)), (a = l.length)), - (y = n === a), - (u = u || y); + rootData: a, + }) || ((i = null === i ? s.errors : i.concat(s.errors)), (l = i.length)), + (y = n === l), + (f = f || y); } - if (!u) { - const e = { params: {} }; - return null === l ? (l = [e]) : l.push(e), a++, (n.errors = l), !1; + if (!f) { + const r = { params: {} }; + return null === i ? (i = [r]) : i.push(r), l++, (n.errors = i), !1; } return ( - (a = p), - null !== l && (p ? (l.length = p) : (l = null)), - (n.errors = l), - 0 === a + (l = p), + null !== i && (p ? (i.length = p) : (i = null)), + (n.errors = i), + 0 === l ); } -function r( - e, +function o( + r, { - instancePath: t = '', - parentData: s, - parentDataProperty: o, - rootData: i = e, + instancePath: e = '', + parentData: t, + parentDataProperty: s, + rootData: a = r, } = {}, ) { - let l = null, - a = 0; - if (0 === a) { - if (!e || 'object' != typeof e || Array.isArray(e)) - return (r.errors = [{ params: { type: 'object' } }]), !1; + let i = null, + l = 0; + if (0 === l) { + if (!r || 'object' != typeof r || Array.isArray(r)) + return (o.errors = [{ params: { type: 'object' } }]), !1; { - let s; - if (void 0 === e.provides && (s = 'provides')) - return (r.errors = [{ params: { missingProperty: s } }]), !1; + let t; + if (void 0 === r.provides && (t = 'provides')) + return (o.errors = [{ params: { missingProperty: t } }]), !1; { - const s = a; - for (const t in e) - if ('provides' !== t && 'shareScope' !== t) - return (r.errors = [{ params: { additionalProperty: t } }]), !1; - if (s === a) { - if (void 0 !== e.provides) { - const s = a; - n(e.provides, { - instancePath: t + '/provides', - parentData: e, + const t = l; + for (const e in r) + if ('provides' !== e && 'shareScope' !== e && 'experiments' !== e) + return (o.errors = [{ params: { additionalProperty: e } }]), !1; + if (t === l) { + if (void 0 !== r.provides) { + const t = l; + n(r.provides, { + instancePath: e + '/provides', + parentData: r, parentDataProperty: 'provides', - rootData: i, + rootData: a, }) || - ((l = null === l ? n.errors : l.concat(n.errors)), - (a = l.length)); - var p = s === a; + ((i = null === i ? n.errors : i.concat(n.errors)), + (l = i.length)); + var p = t === l; } else p = !0; - if (p) - if (void 0 !== e.shareScope) { - let t = e.shareScope; - const s = a, - n = a; - let o = !1; - const i = a; - if (a === i) - if ('string' == typeof t) { - if (t.length < 1) { - const e = { params: {} }; - null === l ? (l = [e]) : l.push(e), a++; + if (p) { + if (void 0 !== r.shareScope) { + let e = r.shareScope; + const t = l, + s = l; + let n = !1; + const a = l; + if (l === a) + if ('string' == typeof e) { + if (e.length < 1) { + const r = { params: {} }; + null === i ? (i = [r]) : i.push(r), l++; } } else { - const e = { params: { type: 'string' } }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: { type: 'string' } }; + null === i ? (i = [r]) : i.push(r), l++; } - var u = i === a; - if (((o = o || u), !o)) { - const e = a; - if (a === e) - if (Array.isArray(t)) { - const e = t.length; - for (let s = 0; s < e; s++) { - let e = t[s]; - const n = a; - if (a === n) - if ('string' == typeof e) { - if (e.length < 1) { - const e = { params: {} }; - null === l ? (l = [e]) : l.push(e), a++; + var f = a === l; + if (((n = n || f), !n)) { + const r = l; + if (l === r) + if (Array.isArray(e)) { + const r = e.length; + for (let t = 0; t < r; t++) { + let r = e[t]; + const s = l; + if (l === s) + if ('string' == typeof r) { + if (r.length < 1) { + const r = { params: {} }; + null === i ? (i = [r]) : i.push(r), l++; } } else { - const e = { params: { type: 'string' } }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: { type: 'string' } }; + null === i ? (i = [r]) : i.push(r), l++; } - if (n !== a) break; + if (s !== l) break; } } else { - const e = { params: { type: 'array' } }; - null === l ? (l = [e]) : l.push(e), a++; + const r = { params: { type: 'array' } }; + null === i ? (i = [r]) : i.push(r), l++; } - (u = e === a), (o = o || u); + (f = r === l), (n = n || f); } - if (!o) { - const e = { params: {} }; + if (!n) { + const r = { params: {} }; return ( - null === l ? (l = [e]) : l.push(e), a++, (r.errors = l), !1 + null === i ? (i = [r]) : i.push(r), l++, (o.errors = i), !1 ); } - (a = n), - null !== l && (n ? (l.length = n) : (l = null)), - (p = s === a); + (l = s), + null !== i && (s ? (i.length = s) : (i = null)), + (p = t === l); } else p = !0; + if (p) + if (void 0 !== r.experiments) { + let e = r.experiments; + const t = l; + if (l === t) { + if (!e || 'object' != typeof e || Array.isArray(e)) + return (o.errors = [{ params: { type: 'object' } }]), !1; + { + const r = l; + for (const r in e) + if ('nodeModulesReconstructedLookup' !== r) + return ( + (o.errors = [{ params: { additionalProperty: r } }]), + !1 + ); + if ( + r === l && + void 0 !== e.nodeModulesReconstructedLookup && + 'boolean' != typeof e.nodeModulesReconstructedLookup + ) + return (o.errors = [{ params: { type: 'boolean' } }]), !1; + } + } + p = t === l; + } else p = !0; + } } } } } - return (r.errors = l), 0 === a; + return (o.errors = i), 0 === l; } diff --git a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.json b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.json index a6afbdddbfb..f4410c5f21f 100644 --- a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.json +++ b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.json @@ -101,49 +101,17 @@ } ] }, + "exclude": { + "description": "Filter for the shared module.", + "$ref": "#/definitions/Exclude" + }, "include": { - "description": "Include filters for providing shared modules.", - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "description": "Version requirement that must be satisfied for the module to be provided.", - "type": "string" - }, - "request": { - "description": "Request pattern that must match for the module to be provided.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "RegExp" - } - ] - } - } + "description": "Options for including only certain versions or requests of the provided module. Cannot be used with 'exclude'.", + "$ref": "#/definitions/IncludeExcludeOptions" }, - "exclude": { - "description": "Exclude filters for providing shared modules.", - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "description": "Version requirement that if satisfied will exclude the module from being provided.", - "type": "string" - }, - "request": { - "description": "Request pattern that if matched will exclude the module from being provided.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "RegExp" - } - ] - } - } + "nodeModulesReconstructedLookup": { + "description": "Enable reconstructed lookup for node_modules paths for this share item", + "type": "boolean" } } }, @@ -166,6 +134,59 @@ } ] } + }, + "Exclude": { + "description": "Advanced filtering options.", + "type": "object", + "additionalProperties": false, + "properties": { + "request": { + "description": "Regular expression pattern to filter module requests", + "instanceof": "RegExp" + }, + "version": { + "description": "Specific version string or range to filter by (exclude matches).", + "type": "string" + }, + "fallbackVersion": { + "description": "Optional specific version string to check against the exclude.version range instead of reading package.json.", + "type": "string" + } + } + }, + "ProvidesList": { + "type": "array", + "description": "A list of module requests to be provided to the shared scope.", + "items": { + "type": "string" + } + }, + "IncludeExcludeOptions": { + "type": "object", + "properties": { + "request": { + "anyOf": [ + { + "type": "string", + "description": "Request string to match exactly." + }, + { + "instanceof": "RegExp", + "description": "Regular expression to match the request path." + } + ] + }, + "version": { + "type": "string", + "description": "Semantic versioning range to match against the module's version." + }, + "fallbackVersion": { + "type": "string", + "description": "Optional specific version string to check against the version range instead of reading package.json." + } + }, + "additionalProperties": false, + "anyOf": [{ "required": ["request"] }, { "required": ["version"] }] } }, "title": "ProvideSharedPluginOptions", @@ -190,6 +211,17 @@ } } ] + }, + "experiments": { + "description": "Experimental features configuration", + "type": "object", + "additionalProperties": false, + "properties": { + "nodeModulesReconstructedLookup": { + "description": "Enable reconstructed lookup for node_modules paths", + "type": "boolean" + } + } } }, "required": ["provides"] diff --git a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.ts b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.ts index 5ad3f187b93..fbd0f96d308 100644 --- a/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.ts +++ b/packages/enhanced/src/schemas/sharing/ProvideSharedPlugin.ts @@ -118,53 +118,19 @@ export default { }, ], }, + exclude: { + description: 'Filter for the shared module.', + $ref: '#/definitions/Exclude', + }, include: { - description: 'Include filters for providing shared modules.', - type: 'object', - additionalProperties: false, - properties: { - version: { - description: - 'Version requirement that must be satisfied for the module to be provided.', - type: 'string', - }, - request: { - description: - 'Request pattern that must match for the module to be provided.', - anyOf: [ - { - type: 'string', - }, - { - instanceof: 'RegExp', - }, - ], - }, - }, + description: + "Options for including only certain versions or requests of the provided module. Cannot be used with 'exclude'.", + $ref: '#/definitions/IncludeExcludeOptions', }, - exclude: { - description: 'Exclude filters for providing shared modules.', - type: 'object', - additionalProperties: false, - properties: { - version: { - description: - 'Version requirement that if satisfied will exclude the module from being provided.', - type: 'string', - }, - request: { - description: - 'Request pattern that if matched will exclude the module from being provided.', - anyOf: [ - { - type: 'string', - }, - { - instanceof: 'RegExp', - }, - ], - }, - }, + nodeModulesReconstructedLookup: { + description: + 'Enable reconstructed lookup for node_modules paths for this share item', + type: 'boolean', }, }, }, @@ -191,6 +157,71 @@ export default { ], }, }, + Exclude: { + description: 'Advanced filtering options.', + type: 'object', + additionalProperties: false, + properties: { + request: { + description: 'Regular expression pattern to filter module requests', + instanceof: 'RegExp', + }, + version: { + description: + 'Specific version string or range to filter by (exclude matches).', + type: 'string', + }, + fallbackVersion: { + description: + 'Optional specific version string to check against the exclude.version range instead of reading package.json.', + type: 'string', + }, + }, + }, + ProvidesList: { + type: 'array', + description: + 'A list of module requests to be provided to the shared scope.', + items: { + type: 'string', + }, + }, + IncludeExcludeOptions: { + type: 'object', + properties: { + request: { + anyOf: [ + { + type: 'string', + description: 'Request string to match exactly.', + }, + { + instanceof: 'RegExp', + description: 'Regular expression to match the request path.', + }, + ], + }, + version: { + type: 'string', + description: + "Semantic versioning range to match against the module's version.", + }, + fallbackVersion: { + type: 'string', + description: + 'Optional specific version string to check against the version range instead of reading package.json.', + }, + }, + additionalProperties: false, + anyOf: [ + { + required: ['request'], + }, + { + required: ['version'], + }, + ], + }, }, title: 'ProvideSharedPluginOptions', type: 'object', @@ -216,6 +247,17 @@ export default { }, ], }, + experiments: { + description: 'Experimental features configuration', + type: 'object', + additionalProperties: false, + properties: { + nodeModulesReconstructedLookup: { + description: 'Enable reconstructed lookup for node_modules paths', + type: 'boolean', + }, + }, + }, }, required: ['provides'], } as const; diff --git a/packages/enhanced/src/schemas/sharing/SharePlugin.json b/packages/enhanced/src/schemas/sharing/SharePlugin.json index 8161043a1b7..f2e8836d8ce 100644 --- a/packages/enhanced/src/schemas/sharing/SharePlugin.json +++ b/packages/enhanced/src/schemas/sharing/SharePlugin.json @@ -189,15 +189,9 @@ }, "additionalProperties": false, "anyOf": [ - { - "required": ["request"] - }, - { - "required": ["version"] - }, - { - "required": ["fallbackVersion"] - } + { "required": ["request"] }, + { "required": ["version"] }, + { "required": ["fallbackVersion"] } ] } }, diff --git a/packages/enhanced/test/configCases/sharing/layers-consume-loader/webpack.config.js b/packages/enhanced/test/configCases/sharing/layers-consume-loader/webpack.config.js index 54db2b386ea..41219b2f397 100644 --- a/packages/enhanced/test/configCases/sharing/layers-consume-loader/webpack.config.js +++ b/packages/enhanced/test/configCases/sharing/layers-consume-loader/webpack.config.js @@ -132,6 +132,8 @@ module.exports = { requiredVersion: '^2.0.0', strictVersion: true, eager: true, + issuerLayer: 'prefixed-layer', + layer: 'multi-pkg-layer', }, }, }), diff --git a/packages/enhanced/test/configCases/sharing/provide-filters/index.js b/packages/enhanced/test/configCases/sharing/provide-filters/index.js index 0d7848edd11..07f524853f8 100644 --- a/packages/enhanced/test/configCases/sharing/provide-filters/index.js +++ b/packages/enhanced/test/configCases/sharing/provide-filters/index.js @@ -87,7 +87,7 @@ it('should not provide modules that fail version include filters', async () => { expect( __webpack_require__.S['default']['version-include-fail'], ).toBeUndefined(); - expectWarning(/does not satisfy include filter/); + expectWarning(); }); it('should not provide modules that fail version exclude filters', async () => { @@ -102,7 +102,7 @@ it('should not provide modules that fail version exclude filters', async () => { expect( __webpack_require__.S['default']['version-exclude-fail'], ).toBeUndefined(); - expectWarning(/matches exclude filter/); + expectWarning(); }); it('should warn about singleton filters', async () => { @@ -118,7 +118,7 @@ it('should warn about singleton filters', async () => { expect( __webpack_require__.S['default']['singleton-filter']['1.0.0'], ).toBeDefined(); - expectWarning(/singleton.*include.*version/); + expectWarning(); }); it('should provide modules that match request include filters', async () => { @@ -129,10 +129,14 @@ it('should provide modules that match request include filters', async () => { const button = await import('./request-filter/components/Button.js'); expect(button.default).toBe('Button'); - // Check that the module was provided to the share scope - expect(__webpack_require__.S['default']['request-prefix']).toBeDefined(); + // Check that the module was provided to the share scope with the full key + expect( + __webpack_require__.S['default']['request-prefixcomponents/Button.js'], + ).toBeDefined(); expect( - __webpack_require__.S['default']['request-prefix']['1.0.0'], + __webpack_require__.S['default']['request-prefixcomponents/Button.js'][ + '1.0.0' + ], ).toBeDefined(); expectWarning(); }); diff --git a/packages/enhanced/test/configCases/sharing/provide-filters/webpack.config.js b/packages/enhanced/test/configCases/sharing/provide-filters/webpack.config.js index 9268628c3d7..52996c315bf 100644 --- a/packages/enhanced/test/configCases/sharing/provide-filters/webpack.config.js +++ b/packages/enhanced/test/configCases/sharing/provide-filters/webpack.config.js @@ -7,28 +7,28 @@ module.exports = { new ProvideSharedPlugin({ provides: { // Version filtering tests - './version-include': { + './version-include.js': { shareKey: 'version-include', version: '1.2.0', include: { version: '^1.0.0', }, }, - './version-exclude': { + './version-exclude.js': { shareKey: 'version-exclude', version: '1.2.0', exclude: { version: '^2.0.0', }, }, - './version-include-fail': { + './version-include-fail.js': { shareKey: 'version-include-fail', version: '1.2.0', include: { version: '^2.0.0', }, }, - './version-exclude-fail': { + './version-exclude-fail.js': { shareKey: 'version-exclude-fail', version: '2.0.0', exclude: { @@ -36,7 +36,7 @@ module.exports = { }, }, // Singleton with filters - './singleton-filter': { + './singleton-filter.js': { shareKey: 'singleton-filter', version: '1.0.0', singleton: true, diff --git a/packages/enhanced/test/unit/sharing/fallback-version.test.ts b/packages/enhanced/test/unit/sharing/fallback-version.test.ts new file mode 100644 index 00000000000..3b60e1cdc07 --- /dev/null +++ b/packages/enhanced/test/unit/sharing/fallback-version.test.ts @@ -0,0 +1,416 @@ +import { satisfy } from '@module-federation/runtime-tools/runtime-core'; + +describe('Fallback Version Filtering', () => { + describe('Include Version Filtering', () => { + it('should check if fallbackVersion satisfies the include filter version range', () => { + const includeVersion = '^18.0.0'; + const fallbackVersion = '18.2.0'; + + // fallbackVersion satisfies the filter, so module should be included + expect(satisfy(fallbackVersion, includeVersion)).toBe(true); + }); + + it('should exclude module if fallbackVersion does not satisfy include filter', () => { + const includeVersion = '^5.0.0'; + const fallbackVersion = '4.17.0'; + + // fallbackVersion doesn't satisfy the filter, so module should be excluded + expect(satisfy(fallbackVersion, includeVersion)).toBe(false); + }); + + it('should handle complex version ranges with fallbackVersion', () => { + const includeVersion = '>=2.0.0 <3.0.0'; + + expect(satisfy('2.5.0', includeVersion)).toBe(true); // should include + expect(satisfy('1.9.0', includeVersion)).toBe(false); // should exclude + expect(satisfy('3.0.0', includeVersion)).toBe(false); // should exclude + }); + }); + + describe('Exclude Version Filtering', () => { + it('should check if fallbackVersion satisfies the exclude filter version range', () => { + const excludeVersion = '^3.0.0'; + const fallbackVersion = '3.0.0'; + + // fallbackVersion satisfies the filter, so module should be excluded + expect(satisfy(fallbackVersion, excludeVersion)).toBe(true); + }); + + it('should NOT exclude module if fallbackVersion does not satisfy exclude filter', () => { + const excludeVersion = '^3.0.0'; + const fallbackVersion = '2.6.0'; + + // fallbackVersion doesn't satisfy the filter, so module should NOT be excluded + expect(satisfy(fallbackVersion, excludeVersion)).toBe(false); + }); + }); + + describe('Edge Cases', () => { + it('should handle empty string fallbackVersion', () => { + const actualVersion = '1.0.0'; + const fallbackVersion = ''; + const includeVersion = '^1.0.0'; + + // Empty string should be ignored, use actual version + const versionToCheck = fallbackVersion || actualVersion; + expect(versionToCheck).toBe(actualVersion); + expect(satisfy(versionToCheck, includeVersion)).toBe(true); + }); + + it('should handle null/undefined actual version with fallbackVersion', () => { + const actualVersion = undefined; + const fallbackVersion = '2.0.0'; + const includeVersion = '^2.0.0'; + + const versionToCheck = fallbackVersion || actualVersion; + expect(versionToCheck).toBe(fallbackVersion); + expect(satisfy(versionToCheck, includeVersion)).toBe(true); + }); + + it('should handle invalid version strings in fallbackVersion', () => { + const fallbackVersion = 'invalid-version'; + const includeVersion = '^1.0.0'; + + // Invalid version should return false + expect(satisfy(fallbackVersion, includeVersion)).toBe(false); + }); + }); + + describe('ConsumeSharedPlugin Behavior', () => { + it('should use fallbackVersion to determine if module satisfies include filter', () => { + const config = { + include: { + version: '^18.0.0', + fallbackVersion: '18.2.0', + }, + }; + + // Check if fallbackVersion satisfies the include filter + const shouldInclude = satisfy( + config.include.fallbackVersion, + config.include.version, + ); + expect(shouldInclude).toBe(true); // Module should be included + }); + + it('should use fallbackVersion to determine if module satisfies exclude filter', () => { + const config = { + exclude: { + version: '^3.0.0', + fallbackVersion: '3.0.0', + }, + }; + + // Check if fallbackVersion satisfies the exclude filter + const shouldExclude = satisfy( + config.exclude.fallbackVersion, + config.exclude.version, + ); + expect(shouldExclude).toBe(true); // Module should be excluded + }); + + it('should NOT include module if fallbackVersion does not satisfy include filter', () => { + const config = { + include: { + version: '^5.0.0', + fallbackVersion: '4.17.0', + }, + }; + + const shouldInclude = satisfy( + config.include.fallbackVersion, + config.include.version, + ); + expect(shouldInclude).toBe(false); // Module should NOT be included + }); + }); + + describe('ProvideSharedPlugin Behavior', () => { + it('should simulate include filter with fallbackVersion for provided modules', () => { + const config = { + version: '17.0.0', // Actual version from package.json + include: { + version: '^18.0.0', + fallbackVersion: '18.2.0', + }, + }; + + const versionToCheck = config.include.fallbackVersion || config.version; + const shouldProvide = satisfy(versionToCheck, config.include.version); + + expect(versionToCheck).toBe('18.2.0'); + expect(shouldProvide).toBe(true); + }); + + it('should simulate exclude filter with fallbackVersion for provided modules', () => { + const config = { + version: '18.0.0', // Actual version + exclude: { + version: '^16.0.0', + fallbackVersion: '16.8.0', + }, + }; + + const versionToCheck = config.exclude.fallbackVersion || config.version; + const shouldExclude = satisfy(versionToCheck, config.exclude.version); + + expect(versionToCheck).toBe('16.8.0'); + expect(shouldExclude).toBe(true); // Should be excluded + }); + + it('should simulate ProvideSharedPlugin filtering logic', () => { + // Simulate the actual filtering logic used in ProvideSharedPlugin + const testCases = [ + { + name: 'include filter passes with fallbackVersion', + actualVersion: '1.2.0', + config: { + include: { + version: '^2.0.0', + fallbackVersion: '2.1.0', + }, + }, + expected: true, // Should provide because fallbackVersion satisfies include + }, + { + name: 'include filter fails even with fallbackVersion', + actualVersion: '1.2.0', + config: { + include: { + version: '^2.0.0', + fallbackVersion: '1.5.0', + }, + }, + expected: false, // Should not provide because fallbackVersion doesn't satisfy include + }, + { + name: 'exclude filter triggers with fallbackVersion', + actualVersion: '2.0.0', + config: { + exclude: { + version: '^1.0.0', + fallbackVersion: '1.5.0', + }, + }, + expected: false, // Should not provide because fallbackVersion matches exclude + }, + { + name: 'exclude filter does not trigger with fallbackVersion', + actualVersion: '2.0.0', + config: { + exclude: { + version: '^1.0.0', + fallbackVersion: '3.0.0', + }, + }, + expected: true, // Should provide because fallbackVersion doesn't match exclude + }, + ]; + + testCases.forEach((testCase) => { + // Simulate ProvideSharedPlugin include filtering logic + let shouldProvide = true; + + if (testCase.config.include) { + let versionIncludeFailed = false; + if (typeof testCase.config.include.version === 'string') { + if ( + typeof testCase.actualVersion === 'string' && + testCase.actualVersion + ) { + if ( + !satisfy( + testCase.actualVersion, + testCase.config.include.version, + ) + ) { + versionIncludeFailed = true; + } + } else { + versionIncludeFailed = true; + } + } + + // Check fallback version for include + if ( + versionIncludeFailed && + testCase.config.include && + typeof testCase.config.include.fallbackVersion === 'string' && + testCase.config.include.fallbackVersion + ) { + if ( + satisfy( + testCase.config.include.fallbackVersion, + testCase.config.include.version, + ) + ) { + versionIncludeFailed = false; // fallbackVersion satisfies, so include + } + } + + if (versionIncludeFailed) { + shouldProvide = false; + } + } + + if (testCase.config.exclude && shouldProvide) { + let versionExcludeMatches = false; + if ( + typeof testCase.config.exclude.version === 'string' && + typeof testCase.actualVersion === 'string' && + testCase.actualVersion + ) { + if ( + satisfy(testCase.actualVersion, testCase.config.exclude.version) + ) { + versionExcludeMatches = true; + } + } + + // Check fallback version for exclude + if ( + !versionExcludeMatches && + testCase.config.exclude && + typeof testCase.config.exclude.fallbackVersion === 'string' && + testCase.config.exclude.fallbackVersion + ) { + if ( + satisfy( + testCase.config.exclude.fallbackVersion, + testCase.config.exclude.version, + ) + ) { + versionExcludeMatches = true; // fallbackVersion satisfies, so exclude + } + } + + if (versionExcludeMatches) { + shouldProvide = false; + } + } + + expect(shouldProvide).toBe(testCase.expected); + }); + }); + }); + + describe('Complex Scenarios', () => { + it('should handle multiple filter combinations with fallbackVersion', () => { + const scenarios = [ + { + description: 'Both include and exclude with fallbackVersion', + actualVersion: '2.5.0', + include: { version: '^3.0.0', fallbackVersion: '3.1.0' }, + exclude: { version: '^2.0.0', fallbackVersion: '1.0.0' }, + expectedResult: false, // actualVersion matches exclude version, so excluded + }, + { + description: + 'Include passes but exclude also matches with fallbackVersion', + actualVersion: '1.0.0', + include: { version: '^2.0.0', fallbackVersion: '2.1.0' }, + exclude: { version: '^2.0.0', fallbackVersion: '2.2.0' }, + expectedResult: false, // Both match, but exclude takes precedence + }, + ]; + + scenarios.forEach((scenario) => { + // Test the logic for each scenario + let shouldInclude = true; + + // Include check + if (scenario.include) { + let includeFailsWithActual = !satisfy( + scenario.actualVersion, + scenario.include.version, + ); + if (includeFailsWithActual && scenario.include.fallbackVersion) { + includeFailsWithActual = !satisfy( + scenario.include.fallbackVersion, + scenario.include.version, + ); + } + if (includeFailsWithActual) { + shouldInclude = false; + } + } + + // Exclude check + if (scenario.exclude && shouldInclude) { + let excludeMatchesActual = satisfy( + scenario.actualVersion, + scenario.exclude.version, + ); + if (!excludeMatchesActual && scenario.exclude.fallbackVersion) { + excludeMatchesActual = satisfy( + scenario.exclude.fallbackVersion, + scenario.exclude.version, + ); + } + if (excludeMatchesActual) { + shouldInclude = false; + } + } + + expect(shouldInclude).toBe(scenario.expectedResult); + }); + }); + + it('should handle edge cases with empty and invalid versions', () => { + const edgeCases = [ + { + description: 'Empty actualVersion with valid fallbackVersion', + actualVersion: '', + include: { version: '^1.0.0', fallbackVersion: '1.2.0' }, + expectedResult: true, + }, + { + description: 'Invalid actualVersion with valid fallbackVersion', + actualVersion: 'not-a-version', + include: { version: '^1.0.0', fallbackVersion: '1.2.0' }, + expectedResult: true, + }, + { + description: 'Valid actualVersion with invalid fallbackVersion', + actualVersion: '1.2.0', + include: { version: '^2.0.0', fallbackVersion: 'invalid' }, + expectedResult: false, // Actual doesn't satisfy, fallback is invalid + }, + ]; + + edgeCases.forEach((edgeCase) => { + let shouldInclude = true; + + if (edgeCase.include) { + let includeFailsWithActual = false; + + // Check if actual version satisfies + if ( + !edgeCase.actualVersion || + !satisfy(edgeCase.actualVersion, edgeCase.include.version) + ) { + includeFailsWithActual = true; + } + + // If actual version fails, try fallback + if (includeFailsWithActual && edgeCase.include.fallbackVersion) { + if ( + satisfy( + edgeCase.include.fallbackVersion, + edgeCase.include.version, + ) + ) { + includeFailsWithActual = false; + } + } + + if (includeFailsWithActual) { + shouldInclude = false; + } + } + + expect(shouldInclude).toBe(edgeCase.expectedResult); + }); + }); + }); +}); diff --git a/packages/webpack-bundler-runtime/src/consumes.ts b/packages/webpack-bundler-runtime/src/consumes.ts index 41f025083f4..e76fbe41833 100644 --- a/packages/webpack-bundler-runtime/src/consumes.ts +++ b/packages/webpack-bundler-runtime/src/consumes.ts @@ -20,7 +20,27 @@ export function consumes(options: ConsumesOptions) { installedModules[id] = 0; webpackRequire.m[id] = (module) => { delete webpackRequire.c[id]; - module.exports = factory(); + const result = factory(); + // Add layer property from shareConfig if available + const { shareInfo } = moduleToHandlerMapping[id]; + if ( + shareInfo?.shareConfig?.layer && + result && + typeof result === 'object' + ) { + try { + // Only set layer if it's not already defined or if it's undefined + if ( + !result.hasOwnProperty('layer') || + (result as any).layer === undefined + ) { + (result as any).layer = shareInfo.shareConfig.layer; + } + } catch (e) { + // Ignore if layer property is read-only + } + } + module.exports = result; }; }; const onError = (error: unknown) => { diff --git a/packages/webpack-bundler-runtime/src/installInitialConsumes.ts b/packages/webpack-bundler-runtime/src/installInitialConsumes.ts index 5abcdaaab3a..f6cc3aa2077 100644 --- a/packages/webpack-bundler-runtime/src/installInitialConsumes.ts +++ b/packages/webpack-bundler-runtime/src/installInitialConsumes.ts @@ -47,7 +47,27 @@ export function installInitialConsumes(options: InstallInitialConsumesOptions) { `Shared module is not available for eager consumption: ${id}`, ); } - module.exports = factory(); + const result = factory(); + // Add layer property from shareConfig if available + const { shareInfo } = moduleToHandlerMapping[id]; + if ( + shareInfo?.shareConfig?.layer && + result && + typeof result === 'object' + ) { + try { + // Only set layer if it's not already defined or if it's undefined + if ( + !result.hasOwnProperty('layer') || + (result as any).layer === undefined + ) { + (result as any).layer = shareInfo.shareConfig.layer; + } + } catch (e) { + // Ignore if layer property is read-only + } + } + module.exports = result; }; }); }