1
- import type { RuleSetRuleUnion , Loader } from '@module-federation/utilities' ;
1
+ import type {
2
+ RuleSetRule ,
3
+ RuleSetCondition ,
4
+ RuleSetConditionAbsolute ,
5
+ RuleSetUseItem ,
6
+ } from 'webpack' ;
2
7
3
- /**
4
- * This function injects a loader into the current module rule.
5
- * Note: This function mutates the `rule` argument.
6
- *
7
- * @param {RuleSetRuleUnion } rule - The current module rule.
8
- * @param {Loader } [loader={}] - The loader to be injected.
9
- */
10
- export function injectRuleLoader ( rule : RuleSetRuleUnion , loader : Loader = { } ) {
8
+ export function injectRuleLoader ( rule : any , loader : RuleSetUseItem = { } ) {
11
9
if ( rule !== '...' ) {
12
10
const _rule = rule as {
13
11
loader ?: string ;
14
- use ?: ( Loader | string ) [ ] ;
12
+ use ?: ( RuleSetUseItem | string ) [ ] ;
15
13
options ?: any ;
16
14
} ;
17
15
if ( _rule . loader ) {
@@ -27,23 +25,23 @@ export function injectRuleLoader(rule: RuleSetRuleUnion, loader: Loader = {}) {
27
25
/**
28
26
* This function checks if the current module rule has a loader with the provided name.
29
27
*
30
- * @param {RuleSetRuleUnion } rule - The current module rule.
28
+ * @param {RuleSetRule } rule - The current module rule.
31
29
* @param {string } loaderName - The name of the loader to check.
32
30
* @returns {boolean } Returns true if the current module rule has a loader with the provided name, otherwise false.
33
31
*/
34
- export function hasLoader ( rule : RuleSetRuleUnion , loaderName : string ) {
32
+ export function hasLoader ( rule : RuleSetRule , loaderName : string ) {
33
+ //@ts -ignore
35
34
if ( rule !== '...' ) {
36
35
const _rule = rule as {
37
36
loader ?: string ;
38
- use ?: ( Loader | string ) [ ] ;
37
+ use ?: ( RuleSetUseItem | string ) [ ] ;
39
38
options ?: any ;
40
39
} ;
41
40
if ( _rule . loader === loaderName ) {
42
41
return true ;
43
42
} else if ( _rule . use && Array . isArray ( _rule . use ) ) {
44
43
for ( let i = 0 ; i < _rule . use . length ; i ++ ) {
45
44
const loader = _rule . use [ i ] ;
46
- // check exact name, eg "url-loader" or its path "node_modules/url-loader/dist/cjs.js"
47
45
if (
48
46
typeof loader !== 'string' &&
49
47
typeof loader !== 'function' &&
@@ -62,3 +60,133 @@ export function hasLoader(rule: RuleSetRuleUnion, loaderName: string) {
62
60
}
63
61
return false ;
64
62
}
63
+
64
+ interface Resource {
65
+ path : string ;
66
+ layer ?: string ;
67
+ issuerLayer ?: string ;
68
+ }
69
+
70
+ function matchesCondition (
71
+ condition :
72
+ | RuleSetCondition
73
+ | RuleSetConditionAbsolute
74
+ | RuleSetRule
75
+ | undefined ,
76
+ resource : Resource ,
77
+ currentPath : string ,
78
+ ) : boolean {
79
+ if ( condition instanceof RegExp ) {
80
+ return condition . test ( resource . path ) ;
81
+ } else if ( typeof condition === 'string' ) {
82
+ return resource . path . includes ( condition ) ;
83
+ } else if ( typeof condition === 'function' ) {
84
+ return condition ( resource . path ) ;
85
+ } else if ( typeof condition === 'object' ) {
86
+ if ( 'test' in condition && condition . test ) {
87
+ const tests = Array . isArray ( condition . test )
88
+ ? condition . test
89
+ : [ condition . test ] ;
90
+ if (
91
+ ! tests . some ( ( test : RuleSetCondition ) =>
92
+ matchesCondition ( test , resource , currentPath ) ,
93
+ )
94
+ ) {
95
+ return false ;
96
+ }
97
+ }
98
+ if ( 'include' in condition && condition . include ) {
99
+ const includes = Array . isArray ( condition . include )
100
+ ? condition . include
101
+ : [ condition . include ] ;
102
+ if (
103
+ ! includes . some ( ( include : RuleSetCondition ) =>
104
+ matchesCondition ( include , resource , currentPath ) ,
105
+ )
106
+ ) {
107
+ return false ;
108
+ }
109
+ }
110
+ if ( 'exclude' in condition && condition . exclude ) {
111
+ const excludes = Array . isArray ( condition . exclude )
112
+ ? condition . exclude
113
+ : [ condition . exclude ] ;
114
+ if (
115
+ excludes . some ( ( exclude : RuleSetCondition ) =>
116
+ matchesCondition ( exclude , resource , currentPath ) ,
117
+ )
118
+ ) {
119
+ return false ;
120
+ }
121
+ }
122
+ if ( 'and' in condition && condition . and ) {
123
+ return condition . and . every ( ( cond : RuleSetCondition ) =>
124
+ matchesCondition ( cond , resource , currentPath ) ,
125
+ ) ;
126
+ }
127
+ if ( 'or' in condition && condition . or ) {
128
+ return condition . or . some ( ( cond : RuleSetCondition ) =>
129
+ matchesCondition ( cond , resource , currentPath ) ,
130
+ ) ;
131
+ }
132
+ if ( 'not' in condition && condition . not ) {
133
+ return ! matchesCondition ( condition . not , resource , currentPath ) ;
134
+ }
135
+ if ( 'layer' in condition && condition . layer ) {
136
+ if (
137
+ ! resource . layer ||
138
+ ! matchesCondition (
139
+ condition . layer ,
140
+ { path : resource . layer } ,
141
+ currentPath ,
142
+ )
143
+ ) {
144
+ return false ;
145
+ }
146
+ }
147
+ if ( 'issuerLayer' in condition && condition . issuerLayer ) {
148
+ if (
149
+ ! resource . issuerLayer ||
150
+ ! matchesCondition (
151
+ condition . issuerLayer ,
152
+ { path : resource . issuerLayer } ,
153
+ currentPath ,
154
+ )
155
+ ) {
156
+ return false ;
157
+ }
158
+ }
159
+ }
160
+ return true ;
161
+ }
162
+
163
+ export function findLoaderForResource (
164
+ rules : RuleSetRule [ ] ,
165
+ resource : Resource ,
166
+ path : string [ ] = [ ] ,
167
+ ) : RuleSetRule | null {
168
+ let lastMatchedRule : RuleSetRule | null = null ;
169
+ for ( let i = 0 ; i < rules . length ; i ++ ) {
170
+ const rule = rules [ i ] ;
171
+ const currentPath = [ ...path , `rules[${ i } ]` ] ;
172
+ if ( rule . oneOf ) {
173
+ for ( let j = 0 ; j < rule . oneOf . length ; j ++ ) {
174
+ const subRule = rule . oneOf [ j ] ;
175
+ const subPath = [ ...currentPath , `oneOf[${ j } ]` ] ;
176
+
177
+ if (
178
+ subRule &&
179
+ matchesCondition ( subRule , resource , subPath . join ( '->' ) )
180
+ ) {
181
+ return subRule ;
182
+ }
183
+ }
184
+ } else if (
185
+ rule &&
186
+ matchesCondition ( rule , resource , currentPath . join ( ' -> ' ) )
187
+ ) {
188
+ lastMatchedRule = rule ;
189
+ }
190
+ }
191
+ return lastMatchedRule ;
192
+ }
0 commit comments