@@ -52,36 +52,47 @@ export function resolveWithPaths(
5252 // check if any path mapping rules are relevant
5353 const pathMapOptions = [ ] ;
5454 for ( const pattern in compilerOptions . paths ) {
55- // can only contain zero or one
56- const starIndex = pattern . indexOf ( '*' ) ;
57- if ( starIndex === - 1 ) {
58- if ( pattern === originalRequest ) {
59- pathMapOptions . push ( {
60- partial : '' ,
61- potentials : compilerOptions . paths [ pattern ] ,
62- } ) ;
63- }
64- } else if ( starIndex === 0 && pattern . length === 1 ) {
55+ // get potentials and remove duplicates; JS Set maintains insertion order
56+ const potentials = Array . from ( new Set ( compilerOptions . paths [ pattern ] ) ) ;
57+ if ( potentials . length === 0 ) {
58+ // no potential replacements so skip
59+ continue ;
60+ }
61+
62+ // can only contain zero or one
63+ const starIndex = pattern . indexOf ( '*' ) ;
64+ if ( starIndex === - 1 ) {
65+ if ( pattern === originalRequest ) {
66+ pathMapOptions . push ( {
67+ starIndex,
68+ partial : '' ,
69+ potentials,
70+ } ) ;
71+ }
72+ } else if ( starIndex === 0 && pattern . length === 1 ) {
73+ pathMapOptions . push ( {
74+ starIndex,
75+ partial : originalRequest ,
76+ potentials,
77+ } ) ;
78+ } else if ( starIndex === pattern . length - 1 ) {
79+ if ( originalRequest . startsWith ( pattern . slice ( 0 , - 1 ) ) ) {
6580 pathMapOptions . push ( {
66- partial : originalRequest ,
67- potentials : compilerOptions . paths [ pattern ] ,
81+ starIndex,
82+ partial : originalRequest . slice ( pattern . length - 1 ) ,
83+ potentials,
6884 } ) ;
69- } else if ( starIndex === pattern . length - 1 ) {
70- if ( originalRequest . startsWith ( pattern . slice ( 0 , - 1 ) ) ) {
71- pathMapOptions . push ( {
72- partial : originalRequest . slice ( pattern . length - 1 ) ,
73- potentials : compilerOptions . paths [ pattern ] ,
74- } ) ;
75- }
76- } else {
77- const [ prefix , suffix ] = pattern . split ( '*' ) ;
78- if ( originalRequest . startsWith ( prefix ) && originalRequest . endsWith ( suffix ) ) {
79- pathMapOptions . push ( {
80- partial : originalRequest . slice ( prefix . length ) . slice ( 0 , - suffix . length ) ,
81- potentials : compilerOptions . paths [ pattern ] ,
82- } ) ;
83- }
8485 }
86+ } else {
87+ const [ prefix , suffix ] = pattern . split ( '*' ) ;
88+ if ( originalRequest . startsWith ( prefix ) && originalRequest . endsWith ( suffix ) ) {
89+ pathMapOptions . push ( {
90+ starIndex,
91+ partial : originalRequest . slice ( prefix . length ) . slice ( 0 , - suffix . length ) ,
92+ potentials,
93+ } ) ;
94+ }
95+ }
8596 }
8697
8798 if ( pathMapOptions . length === 0 ) {
@@ -90,7 +101,18 @@ export function resolveWithPaths(
90101 return ;
91102 }
92103
93- if ( pathMapOptions . length === 1 && pathMapOptions [ 0 ] . potentials . length === 1 ) {
104+ // exact matches take priority then largest prefix match
105+ pathMapOptions . sort ( ( a , b ) => {
106+ if ( a . starIndex === - 1 ) {
107+ return - 1 ;
108+ } else if ( b . starIndex === - 1 ) {
109+ return 1 ;
110+ } else {
111+ return b . starIndex - a . starIndex ;
112+ }
113+ } ) ;
114+
115+ if ( pathMapOptions [ 0 ] . potentials . length === 1 ) {
94116 const onlyPotential = pathMapOptions [ 0 ] . potentials [ 0 ] ;
95117 let replacement ;
96118 const starIndex = onlyPotential . indexOf ( '*' ) ;
@@ -109,6 +131,9 @@ export function resolveWithPaths(
109131 return ;
110132 }
111133
134+ // TODO: The following is used when there is more than one potential and will not be
135+ // needed once this is turned into a full webpack resolver plugin
136+
112137 const moduleResolver = ts . resolveModuleName (
113138 originalRequest ,
114139 request . contextInfo . issuer ,
0 commit comments