@@ -15,7 +15,11 @@ import { parse as parseGlob } from 'picomatch';
15
15
import { assertIsError } from '../../utils/error' ;
16
16
import { loadEsmModule } from '../../utils/load-esm' ;
17
17
18
- export async function loadProxyConfiguration ( root : string , proxyConfig : string | undefined ) {
18
+ export async function loadProxyConfiguration (
19
+ root : string ,
20
+ proxyConfig : string | undefined ,
21
+ normalize = false ,
22
+ ) {
19
23
if ( ! proxyConfig ) {
20
24
return undefined ;
21
25
}
@@ -26,13 +30,14 @@ export async function loadProxyConfiguration(root: string, proxyConfig: string |
26
30
throw new Error ( `Proxy configuration file ${ proxyPath } does not exist.` ) ;
27
31
}
28
32
33
+ let proxyConfiguration ;
29
34
switch ( extname ( proxyPath ) ) {
30
35
case '.json' : {
31
36
const content = await readFile ( proxyPath , 'utf-8' ) ;
32
37
33
38
const { parse, printParseErrorCode } = await import ( 'jsonc-parser' ) ;
34
39
const parseErrors : import ( 'jsonc-parser' ) . ParseError [ ] = [ ] ;
35
- const proxyConfiguration = parse ( content , parseErrors , { allowTrailingComma : true } ) ;
40
+ proxyConfiguration = parse ( content , parseErrors , { allowTrailingComma : true } ) ;
36
41
37
42
if ( parseErrors . length > 0 ) {
38
43
let errorMessage = `Proxy configuration file ${ proxyPath } contains parse errors:` ;
@@ -43,47 +48,94 @@ export async function loadProxyConfiguration(root: string, proxyConfig: string |
43
48
throw new Error ( errorMessage ) ;
44
49
}
45
50
46
- return proxyConfiguration ;
51
+ break ;
47
52
}
48
53
case '.mjs' :
49
54
// Load the ESM configuration file using the TypeScript dynamic import workaround.
50
55
// Once TypeScript provides support for keeping the dynamic import this workaround can be
51
56
// changed to a direct dynamic import.
52
- return ( await loadEsmModule < { default : unknown } > ( pathToFileURL ( proxyPath ) ) ) . default ;
57
+ proxyConfiguration = ( await loadEsmModule < { default : unknown } > ( pathToFileURL ( proxyPath ) ) )
58
+ . default ;
59
+ break ;
53
60
case '.cjs' :
54
- return require ( proxyPath ) ;
61
+ proxyConfiguration = require ( proxyPath ) ;
62
+ break ;
55
63
default :
56
64
// The file could be either CommonJS or ESM.
57
65
// CommonJS is tried first then ESM if loading fails.
58
66
try {
59
- return require ( proxyPath ) ;
67
+ proxyConfiguration = require ( proxyPath ) ;
68
+ break ;
60
69
} catch ( e ) {
61
70
assertIsError ( e ) ;
62
71
if ( e . code === 'ERR_REQUIRE_ESM' ) {
63
72
// Load the ESM configuration file using the TypeScript dynamic import workaround.
64
73
// Once TypeScript provides support for keeping the dynamic import this workaround can be
65
74
// changed to a direct dynamic import.
66
- return ( await loadEsmModule < { default : unknown } > ( pathToFileURL ( proxyPath ) ) ) . default ;
75
+ proxyConfiguration = ( await loadEsmModule < { default : unknown } > ( pathToFileURL ( proxyPath ) ) )
76
+ . default ;
77
+ break ;
67
78
}
68
79
69
80
throw e ;
70
81
}
71
82
}
83
+
84
+ if ( normalize ) {
85
+ proxyConfiguration = normalizeProxyConfiguration ( proxyConfiguration ) ;
86
+ }
87
+
88
+ return proxyConfiguration ;
72
89
}
73
90
74
91
/**
75
92
* Converts glob patterns to regular expressions to support Vite's proxy option.
93
+ * Also converts the Webpack supported array form to an object form supported by both.
94
+ *
76
95
* @param proxy A proxy configuration object.
77
96
*/
78
- export function normalizeProxyConfiguration ( proxy : Record < string , unknown > ) {
97
+ function normalizeProxyConfiguration (
98
+ proxy : Record < string , unknown > | object [ ] ,
99
+ ) : Record < string , unknown > {
100
+ let normalizedProxy : Record < string , unknown > | undefined ;
101
+
102
+ if ( Array . isArray ( proxy ) ) {
103
+ // Construct an object-form proxy configuration from the array
104
+ normalizedProxy = { } ;
105
+ for ( const proxyEntry of proxy ) {
106
+ if ( ! ( 'context' in proxyEntry ) ) {
107
+ continue ;
108
+ }
109
+ if ( ! Array . isArray ( proxyEntry . context ) ) {
110
+ continue ;
111
+ }
112
+
113
+ // Array-form entries contain a context string array with the path(s)
114
+ // to use for the configuration entry.
115
+ const context = proxyEntry . context ;
116
+ delete proxyEntry . context ;
117
+ for ( const contextEntry of context ) {
118
+ if ( typeof contextEntry !== 'string' ) {
119
+ continue ;
120
+ }
121
+
122
+ normalizedProxy [ contextEntry ] = proxyEntry ;
123
+ }
124
+ }
125
+ } else {
126
+ normalizedProxy = proxy ;
127
+ }
128
+
79
129
// TODO: Consider upstreaming glob support
80
- for ( const key of Object . keys ( proxy ) ) {
130
+ for ( const key of Object . keys ( normalizedProxy ) ) {
81
131
if ( isDynamicPattern ( key ) ) {
82
132
const { output } = parseGlob ( key ) ;
83
- proxy [ `^${ output } $` ] = proxy [ key ] ;
84
- delete proxy [ key ] ;
133
+ normalizedProxy [ `^${ output } $` ] = normalizedProxy [ key ] ;
134
+ delete normalizedProxy [ key ] ;
85
135
}
86
136
}
137
+
138
+ return normalizedProxy ;
87
139
}
88
140
89
141
/**
0 commit comments