@@ -42,7 +42,7 @@ interface IRigConfigOptions {
4242 rigFound : boolean ;
4343 filePath : string ;
4444 rigPackageName : string ;
45- rigProfile : string ;
45+ rigProfile ? : string ;
4646}
4747
4848/**
@@ -60,6 +60,11 @@ export interface ILoadForProjectFolderOptions {
6060 * If specified, instead of loading the `config/rig.json` from disk, this object will be substituted instead.
6161 */
6262 overrideRigJsonObject ?: IRigConfigJson ;
63+
64+ /**
65+ * If specified, force a fresh load instead of returning a cached entry, if one existed.
66+ */
67+ bypassCache ?: boolean ;
6368}
6469
6570/**
@@ -91,6 +96,8 @@ export class RigConfig {
9196 public static jsonSchemaPath : string = path . resolve ( __dirname , './schemas/rig.schema.json' ) ;
9297 private static _jsonSchemaObject : object | undefined = undefined ;
9398
99+ private static readonly _configCache : Map < string , RigConfig > = new Map ( ) ;
100+
94101 /**
95102 * The project folder path that was passed to {@link RigConfig.loadForProjectFolder},
96103 * which maybe an absolute or relative path.
@@ -160,13 +167,15 @@ export class RigConfig {
160167 private _resolvedProfileFolder : string | undefined ;
161168
162169 private constructor ( options : IRigConfigOptions ) {
163- this . projectFolderOriginalPath = options . projectFolderPath ;
164- this . projectFolderPath = path . resolve ( options . projectFolderPath ) ;
170+ const { projectFolderPath, rigFound, filePath, rigPackageName, rigProfile = 'default' } = options ;
171+
172+ this . projectFolderOriginalPath = projectFolderPath ;
173+ this . projectFolderPath = path . resolve ( projectFolderPath ) ;
165174
166- this . rigFound = options . rigFound ;
167- this . filePath = options . filePath ;
168- this . rigPackageName = options . rigPackageName ;
169- this . rigProfile = options . rigProfile ;
175+ this . rigFound = rigFound ;
176+ this . filePath = filePath ;
177+ this . rigPackageName = rigPackageName ;
178+ this . rigProfile = rigProfile ;
170179
171180 if ( this . rigFound ) {
172181 this . relativeProfileFolderPath = 'profiles/' + this . rigProfile ;
@@ -199,80 +208,110 @@ export class RigConfig {
199208 * equal to `false`.
200209 */
201210 public static loadForProjectFolder ( options : ILoadForProjectFolderOptions ) : RigConfig {
202- const rigConfigFilePath : string = path . join ( options . projectFolderPath , 'config/rig.json' ) ;
211+ const { overrideRigJsonObject , projectFolderPath } = options ;
203212
204- let json : IRigConfigJson ;
205- try {
206- if ( options . overrideRigJsonObject ) {
207- json = options . overrideRigJsonObject ;
208- } else {
209- if ( ! fs . existsSync ( rigConfigFilePath ) ) {
210- return new RigConfig ( {
211- projectFolderPath : options . projectFolderPath ,
212-
213- rigFound : false ,
214- filePath : '' ,
215- rigPackageName : '' ,
216- rigProfile : ''
217- } ) ;
218- }
213+ const fromCache : RigConfig | undefined =
214+ ! options . bypassCache && ! overrideRigJsonObject
215+ ? RigConfig . _configCache . get ( projectFolderPath )
216+ : undefined ;
219217
218+ if ( fromCache ) {
219+ return fromCache ;
220+ }
221+
222+ const rigConfigFilePath : string = path . join ( projectFolderPath , 'config/rig.json' ) ;
223+
224+ let config : RigConfig | undefined ;
225+ let json : IRigConfigJson | undefined = overrideRigJsonObject ;
226+ try {
227+ if ( ! json ) {
220228 const rigConfigFileContent : string = fs . readFileSync ( rigConfigFilePath ) . toString ( ) ;
221- json = JSON . parse ( stripJsonComments ( rigConfigFileContent ) ) ;
229+ json = JSON . parse ( stripJsonComments ( rigConfigFileContent ) ) as IRigConfigJson ;
222230 }
223231 RigConfig . _validateSchema ( json ) ;
224232 } catch ( error ) {
225- throw new Error ( error . message + '\nError loading config file: ' + rigConfigFilePath ) ;
233+ config = RigConfig . _handleConfigError ( error , projectFolderPath , rigConfigFilePath ) ;
226234 }
227235
228- return new RigConfig ( {
229- projectFolderPath : options . projectFolderPath ,
236+ if ( ! config ) {
237+ config = new RigConfig ( {
238+ projectFolderPath : projectFolderPath ,
230239
231- rigFound : true ,
232- filePath : rigConfigFilePath ,
233- rigPackageName : json . rigPackageName ,
234- rigProfile : json . rigProfile || 'default'
235- } ) ;
240+ rigFound : true ,
241+ filePath : rigConfigFilePath ,
242+ rigPackageName : json ! . rigPackageName ,
243+ rigProfile : json ! . rigProfile
244+ } ) ;
245+ }
246+
247+ if ( ! overrideRigJsonObject ) {
248+ RigConfig . _configCache . set ( projectFolderPath , config ) ;
249+ }
250+ return config ;
236251 }
237252
238253 /**
239254 * An async variant of {@link RigConfig.loadForProjectFolder}
240255 */
241256 public static async loadForProjectFolderAsync ( options : ILoadForProjectFolderOptions ) : Promise < RigConfig > {
242- const rigConfigFilePath : string = path . join ( options . projectFolderPath , 'config/rig.json' ) ;
257+ const { overrideRigJsonObject , projectFolderPath } = options ;
243258
244- let json : IRigConfigJson ;
245- try {
246- if ( options . overrideRigJsonObject ) {
247- json = options . overrideRigJsonObject ;
248- } else {
249- if ( ! ( await Helpers . fsExistsAsync ( rigConfigFilePath ) ) ) {
250- return new RigConfig ( {
251- projectFolderPath : options . projectFolderPath ,
252-
253- rigFound : false ,
254- filePath : '' ,
255- rigPackageName : '' ,
256- rigProfile : ''
257- } ) ;
258- }
259+ const fromCache : RigConfig | false | undefined =
260+ ! options . bypassCache && ! overrideRigJsonObject && RigConfig . _configCache . get ( projectFolderPath ) ;
261+
262+ if ( fromCache ) {
263+ return fromCache ;
264+ }
265+
266+ const rigConfigFilePath : string = path . join ( projectFolderPath , 'config/rig.json' ) ;
259267
268+ let config : RigConfig | undefined ;
269+ let json : IRigConfigJson | undefined = overrideRigJsonObject ;
270+ try {
271+ if ( ! json ) {
260272 const rigConfigFileContent : string = ( await fs . promises . readFile ( rigConfigFilePath ) ) . toString ( ) ;
261- json = JSON . parse ( stripJsonComments ( rigConfigFileContent ) ) ;
273+ json = JSON . parse ( stripJsonComments ( rigConfigFileContent ) ) as IRigConfigJson ;
262274 }
263275
264276 RigConfig . _validateSchema ( json ) ;
265277 } catch ( error ) {
278+ config = RigConfig . _handleConfigError ( error , projectFolderPath , rigConfigFilePath ) ;
279+ }
280+
281+ if ( ! config ) {
282+ config = new RigConfig ( {
283+ projectFolderPath : projectFolderPath ,
284+
285+ rigFound : true ,
286+ filePath : rigConfigFilePath ,
287+ rigPackageName : json ! . rigPackageName ,
288+ rigProfile : json ! . rigProfile
289+ } ) ;
290+ }
291+
292+ if ( ! overrideRigJsonObject ) {
293+ RigConfig . _configCache . set ( projectFolderPath , config ) ;
294+ }
295+ return config ;
296+ }
297+
298+ private static _handleConfigError (
299+ error : NodeJS . ErrnoException ,
300+ projectFolderPath : string ,
301+ rigConfigFilePath : string
302+ ) : RigConfig {
303+ if ( error . code !== 'ENOENT' && error . code !== 'ENOTDIR' ) {
266304 throw new Error ( error . message + '\nError loading config file: ' + rigConfigFilePath ) ;
267305 }
268306
307+ // File not found, i.e. no rig config
269308 return new RigConfig ( {
270- projectFolderPath : options . projectFolderPath ,
309+ projectFolderPath,
271310
272- rigFound : true ,
273- filePath : rigConfigFilePath ,
274- rigPackageName : json . rigPackageName ,
275- rigProfile : json . rigProfile || 'default '
311+ rigFound : false ,
312+ filePath : '' ,
313+ rigPackageName : '' ,
314+ rigProfile : ' '
276315 } ) ;
277316 }
278317
0 commit comments