Skip to content

Commit 530ccbb

Browse files
committed
[heft-config-file] Let null reset properties
1 parent 5baf098 commit 530ccbb

6 files changed

Lines changed: 50 additions & 10 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@rushstack/heft-config-file",
5+
"comment": "Allow use of the value `null` to discard any value set for the property from a parent config file..",
6+
"type": "minor"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-config-file"
10+
}

libraries/heft-config-file/src/ConfigurationFileBase.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ interface IConfigurationJson {
1616
* @beta
1717
*
1818
* The set of possible mechanisms for merging properties from parent configuration files.
19+
* If a child configuration file sets a property value to `null`, that will always delete the value
20+
* specified in the parent configuration file, regardless of the inheritance type.
1921
*/
2022
const InheritanceType = {
2123
/**
@@ -251,6 +253,7 @@ export interface ICustomPropertyInheritance<TObject> extends IPropertyInheritanc
251253
* Provides a custom inheritance function. This function takes two arguments: the first is the
252254
* child file's object, and the second is the parent file's object. The function should return
253255
* the resulting combined object.
256+
* This function will not be invoked if the current value is `null`, the property will simply be deleted.
254257
*/
255258
inheritanceFunction: PropertyInheritanceCustomFunction<TObject>;
256259
}
@@ -1085,7 +1088,15 @@ export abstract class ConfigurationFileBase<TConfigurationFile, TExtraOptions ex
10851088
newValue = parentPropertyValue;
10861089
};
10871090

1088-
if (propertyValue !== undefined && parentPropertyValue === undefined) {
1091+
if (propertyValue === null) {
1092+
if (parentPropertyValue !== undefined) {
1093+
resultAnnotation.originalValues[propertyName] = this.getPropertyOriginalValue({
1094+
parentObject: parentObject,
1095+
propertyName: propertyName
1096+
});
1097+
}
1098+
newValue = undefined;
1099+
} else if (propertyValue !== undefined && parentPropertyValue === undefined) {
10891100
usePropertyValue();
10901101
} else if (parentPropertyValue !== undefined && propertyValue === undefined) {
10911102
useParentPropertyValue();
@@ -1207,7 +1218,10 @@ export abstract class ConfigurationFileBase<TConfigurationFile, TExtraOptions ex
12071218
}
12081219
}
12091220

1210-
result[propertyName] = newValue;
1221+
if (newValue !== undefined) {
1222+
// Don't attach the key for undefined values so that they don't enumerate.
1223+
result[propertyName] = newValue;
1224+
}
12111225
}
12121226

12131227
return result;

libraries/heft-config-file/src/test/ConfigurationFile.test.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ describe('ConfigurationFile', () => {
251251
things: string[];
252252
thingsObj: { A: { B: string }; D: { E: string } };
253253
booleanProp: boolean;
254+
stringProp?: string;
254255
}
255256

256257
it('Correctly loads the config file', () => {
@@ -266,7 +267,8 @@ describe('ConfigurationFile', () => {
266267
const expectedConfigFile: ISimpleConfigFile = {
267268
things: ['A', 'B', 'C'],
268269
thingsObj: { A: { B: 'C' }, D: { E: 'F' } },
269-
booleanProp: true
270+
booleanProp: true,
271+
stringProp: 'someValue'
270272
};
271273
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
272274
});
@@ -284,7 +286,8 @@ describe('ConfigurationFile', () => {
284286
const expectedConfigFile: ISimpleConfigFile = {
285287
things: ['A', 'B', 'C'],
286288
thingsObj: { A: { B: 'C' }, D: { E: 'F' } },
287-
booleanProp: true
289+
booleanProp: true,
290+
stringProp: 'someValue'
288291
};
289292
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
290293
});
@@ -317,7 +320,8 @@ describe('ConfigurationFile', () => {
317320
A: { B: nodeJsPath.resolve(__dirname, configFileFolderName, 'C') },
318321
D: { E: nodeJsPath.resolve(__dirname, configFileFolderName, 'F') }
319322
},
320-
booleanProp: true
323+
booleanProp: true,
324+
stringProp: 'someValue'
321325
};
322326
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
323327
});
@@ -350,7 +354,8 @@ describe('ConfigurationFile', () => {
350354
A: { B: nodeJsPath.resolve(__dirname, configFileFolderName, 'C') },
351355
D: { E: nodeJsPath.resolve(__dirname, configFileFolderName, 'F') }
352356
},
353-
booleanProp: true
357+
booleanProp: true,
358+
stringProp: 'someValue'
354359
};
355360
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
356361
});
@@ -383,7 +388,8 @@ describe('ConfigurationFile', () => {
383388
A: { B: nodeJsPath.resolve(projectRoot, 'C') },
384389
D: { E: nodeJsPath.resolve(projectRoot, 'F') }
385390
},
386-
booleanProp: true
391+
booleanProp: true,
392+
stringProp: 'someValue'
387393
};
388394
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
389395
});
@@ -416,7 +422,8 @@ describe('ConfigurationFile', () => {
416422
A: { B: nodeJsPath.resolve(projectRoot, 'C') },
417423
D: { E: nodeJsPath.resolve(projectRoot, 'F') }
418424
},
419-
booleanProp: true
425+
booleanProp: true,
426+
stringProp: 'someValue'
420427
};
421428
expect(JSON.stringify(loadedConfigFile)).toEqual(JSON.stringify(expectedConfigFile));
422429
});
@@ -435,6 +442,7 @@ describe('ConfigurationFile', () => {
435442
things: string[];
436443
thingsObj: { A: { B?: string; D?: string }; D?: { E: string }; F?: { G: string } };
437444
booleanProp: boolean;
445+
stringProp?: string;
438446
}
439447

440448
it('Correctly loads the config file with default config meta', () => {

libraries/heft-config-file/src/test/simpleConfigFile/simpleConfigFile.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@
99
"E": "F"
1010
}
1111
},
12-
"booleanProp": true
12+
"booleanProp": true,
13+
14+
"stringProp": "someValue"
1315
}

libraries/heft-config-file/src/test/simpleConfigFile/simpleConfigFile.schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
"booleanProp": {
2626
"type": "boolean"
27+
},
28+
29+
"stringProp": {
30+
"type": "string"
2731
}
2832
}
2933
}

libraries/heft-config-file/src/test/simpleConfigFileWithExtends/simpleConfigFileWithExtends.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@
1313
}
1414
},
1515

16-
"booleanProp": false
16+
"booleanProp": false,
17+
18+
"stringProp": null
1719
}

0 commit comments

Comments
 (0)