Skip to content

Commit 28f98a5

Browse files
authored
[heft-config-file] Let null reset properties (#5195)
* [heft-config-file] Let null reset properties * Update extends documentation * fix change files --------- Co-authored-by: David Michon <dmichon-msft@users.noreply.github.com>
1 parent 5baf098 commit 28f98a5

File tree

44 files changed

+198
-19
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+198
-19
lines changed

apps/api-extractor/config/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
"extends": "decoupled-local-node-rig/profiles/default/config/heft.json",
1214

apps/heft/src/schemas/heft-legacy.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121

2222
"extends": {
23-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
23+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
2424
"type": "string"
2525
},
2626

apps/heft/src/schemas/heft.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
},
105105

106106
"extends": {
107-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
107+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
108108
"type": "string"
109109
},
110110

apps/heft/src/schemas/node-service.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414

1515
"extends": {
16-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
16+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
1717
"type": "string"
1818
},
1919

apps/heft/src/schemas/templates/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
// "extends": "base-project/config/heft.json",
1214

apps/lockfile-explorer-web/config/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
"extends": "local-web-rig/profiles/app/config/heft.json",
1214

apps/lockfile-explorer/config/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
"extends": "local-node-rig/profiles/default/config/heft.json",
1214

apps/lockfile-explorer/config/node-service.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
/**
99
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
1010
* settings to be shared across multiple projects.
11+
*
12+
* To delete an inherited setting, set it to `null` in this file.
1113
*/
1214
// "extends": "base-project/config/serve-command.json",
1315

build-tests-samples/heft-web-rig-library-tutorial/config/api-extractor.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for
99
* standard settings to be shared across multiple projects.
1010
*
11+
* To delete an inherited setting, set it to `null` in this file.
12+
*
1113
* If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
1214
* the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
1315
* resolved using NodeJS require().

build-tests/heft-fastify-test/config/node-service.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
/**
99
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
1010
* settings to be shared across multiple projects.
11+
*
12+
* To delete an inherited setting, set it to `null` in this file.
1113
*/
1214
// "extends": "base-project/config/serve-command.json",
1315

build-tests/localization-plugin-test-01/config/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
"extends": "local-node-rig/profiles/default/config/heft.json",
1214

build-tests/localization-plugin-test-02/config/heft.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
"extends": "local-node-rig/profiles/default/config/heft.json",
1214

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@microsoft/api-extractor"
7+
}
8+
],
9+
"packageName": "@microsoft/api-extractor",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "none",
6+
"packageName": "@microsoft/rush"
7+
}
8+
],
9+
"packageName": "@microsoft/rush",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft-api-extractor-plugin"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-api-extractor-plugin",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft-node-rig"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-node-rig",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft-sass-plugin"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-sass-plugin",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft-typescript-plugin"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-typescript-plugin",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft-web-rig"
7+
}
8+
],
9+
"packageName": "@rushstack/heft-web-rig",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/heft"
7+
}
8+
],
9+
"packageName": "@rushstack/heft",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Update documentation for `extends`",
5+
"type": "patch",
6+
"packageName": "@rushstack/lockfile-explorer"
7+
}
8+
],
9+
"packageName": "@rushstack/lockfile-explorer",
10+
"email": "dmichon-msft@users.noreply.github.com"
11+
}

heft-plugins/heft-api-extractor-plugin/src/schemas/api-extractor-task.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414

1515
"extends": {
16-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
16+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
1717
"type": "string"
1818
},
1919

heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414

1515
"extends": {
16-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
16+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
1717
"type": "string"
1818
},
1919

heft-plugins/heft-sass-plugin/src/templates/sass.json

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/**
88
* Optionally specifies another JSON config file that this file extends from. This provides a way for standard
99
* settings to be shared across multiple projects.
10+
*
11+
* To delete an inherited setting, set it to `null` in this file.
1012
*/
1113
// "extends": "base-project/config/serve-command.json",
1214

heft-plugins/heft-typescript-plugin/src/schemas/typescript.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414

1515
"extends": {
16-
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.",
16+
"description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects. To delete an inherited setting, set it to `null` in this file.",
1717
"type": "string"
1818
},
1919

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

+16-2
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

+14-6
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', () => {

0 commit comments

Comments
 (0)