Skip to content

Commit 1a6bef2

Browse files
src: set default config as node.config.json
PR-URL: #57171 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 4edc6db commit 1a6bef2

14 files changed

+114
-22
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ doc: $(NODE_EXE) doc-only ## Build Node.js, and then build the documentation wit
809809

810810
out/doc:
811811
mkdir -p $@
812-
cp doc/node_config_json_schema.json $@
812+
cp doc/node-config-schema.json $@
813813

814814
# If it's a source tarball, doc/api already contains the generated docs.
815815
# Just copy everything under doc/api over.

doc/api/cli.md

+22-9
Original file line numberDiff line numberDiff line change
@@ -911,29 +911,30 @@ added: v23.6.0
911911
912912
Enable experimental import support for `.node` addons.
913913

914-
### `--experimental-config-file`
914+
### `--experimental-config-file=config`
915915

916916
<!-- YAML
917917
added: REPLACEME
918918
-->
919919

920920
> Stability: 1.0 - Early development
921921
922-
Use this flag to specify a configuration file that will be loaded and parsed
923-
before the application starts.
922+
If present, Node.js will look for a
923+
configuration file at the specified path.
924924
Node.js will read the configuration file and apply the settings.
925925
The configuration file should be a JSON file
926926
with the following structure:
927927

928+
> \[!NOTE]
929+
> Replace `vX.Y.Z` in the `$schema` with the version of Node.js you are using.
930+
928931
```json
929932
{
930-
"$schema": "https://nodejs.org/dist/REPLACEME/docs/node_config_json_schema.json",
933+
"$schema": "https://nodejs.org/dist/vX.Y.Z/docs/node-config-schema.json",
931934
"nodeOptions": {
932-
"experimental-transform-types": true,
933935
"import": [
934-
"amaro/transform"
936+
"amaro/strip"
935937
],
936-
"disable-warning": "ExperimentalWarning",
937938
"watch-path": "src",
938939
"watch-preserve-output": true
939940
}
@@ -944,7 +945,7 @@ In the `nodeOptions` field, only flags that are allowed in [`NODE_OPTIONS`][] ar
944945
No-op flags are not supported.
945946
Not all V8 flags are currently supported.
946947

947-
It is possible to use the [official JSON schema](../node_config_json_schema.json)
948+
It is possible to use the [official JSON schema](../node-config-schema.json)
948949
to validate the configuration file, which may vary depending on the Node.js version.
949950
Each key in the configuration file corresponds to a flag that can be passed
950951
as a command-line argument. The value of the key is the value that would be
@@ -954,7 +955,7 @@ For example, the configuration file above is equivalent to
954955
the following command-line arguments:
955956

956957
```bash
957-
node --experimental-transform-types --import amaro/transform --disable-warning=ExperimentalWarning --watch-path=src --watch-preserve-output
958+
node --import amaro/strip --watch-path=src --watch-preserve-output
958959
```
959960

960961
The priority in configuration is as follows:
@@ -976,6 +977,18 @@ unknown keys or keys that cannot used in `NODE_OPTIONS`.
976977
Node.js will not sanitize or perform validation on the user-provided configuration,
977978
so **NEVER** use untrusted configuration files.
978979

980+
### `--experimental-default-config-file`
981+
982+
<!-- YAML
983+
added: REPLACEME
984+
-->
985+
986+
> Stability: 1.0 - Early development
987+
988+
If the `--experimental-default-config-file` flag is present, Node.js will look for a
989+
`node.config.json` file in the current working directory and load it as a
990+
as configuration file.
991+
979992
### `--experimental-eventsource`
980993

981994
<!-- YAML
File renamed without changes.

doc/node.1

+4-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ Interpret the entry point as a URL.
167167
Enable experimental addon module support.
168168
.
169169
.It Fl -experimental-config-file
170-
Enable support for experimental config file
170+
Specifies the configuration file to load.
171+
.
172+
.It Fl -experimental-default-config-file
173+
Enable support for automatically loading node.config.json.
171174
.
172175
.It Fl -experimental-import-meta-resolve
173176
Enable experimental ES modules support for import.meta.resolve().

lib/internal/process/pre_execution.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ function setupSQLite() {
315315
}
316316

317317
function initializeConfigFileSupport() {
318-
if (getOptionValue('--experimental-config-file')) {
318+
if (getOptionValue('--experimental-default-config-file') ||
319+
getOptionValue('--experimental-config-file')) {
319320
emitExperimentalWarning('--experimental-config-file');
320321
}
321322
}

src/node_config_file.cc

+15-5
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,32 @@ namespace node {
88

99
std::optional<std::string_view> ConfigReader::GetDataFromArgs(
1010
const std::vector<std::string>& args) {
11-
constexpr std::string_view flag = "--experimental-config-file";
11+
constexpr std::string_view flag_path = "--experimental-config-file";
12+
constexpr std::string_view default_file =
13+
"--experimental-default-config-file";
14+
15+
bool has_default_config_file = false;
1216

1317
for (auto it = args.begin(); it != args.end(); ++it) {
14-
if (*it == flag) {
18+
if (*it == flag_path) {
1519
// Case: "--experimental-config-file foo"
1620
if (auto next = std::next(it); next != args.end()) {
1721
return *next;
1822
}
19-
} else if (it->starts_with(flag)) {
23+
} else if (it->starts_with(flag_path)) {
2024
// Case: "--experimental-config-file=foo"
21-
if (it->size() > flag.size() && (*it)[flag.size()] == '=') {
22-
return it->substr(flag.size() + 1);
25+
if (it->size() > flag_path.size() && (*it)[flag_path.size()] == '=') {
26+
return it->substr(flag_path.size() + 1);
2327
}
28+
} else if (*it == default_file || it->starts_with(default_file)) {
29+
has_default_config_file = true;
2430
}
2531
}
2632

33+
if (has_default_config_file) {
34+
return "node.config.json";
35+
}
36+
2737
return std::nullopt;
2838
}
2939

src/node_options.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
685685
Implies("--env-file-if-exists", "[has_env_file_string]");
686686
AddOption("--experimental-config-file",
687687
"set config file from supplied file",
688-
&EnvironmentOptions::experimental_config_file);
688+
&EnvironmentOptions::experimental_config_file_path);
689+
AddOption("--experimental-default-config-file",
690+
"set config file from default config file",
691+
&EnvironmentOptions::experimental_default_config_file);
689692
AddOption("--test",
690693
"launch test runner on startup",
691694
&EnvironmentOptions::test_runner);

src/node_options.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ class EnvironmentOptions : public Options {
258258

259259
bool report_exclude_env = false;
260260
bool report_exclude_network = false;
261-
std::string experimental_config_file;
261+
std::string experimental_config_file_path;
262+
bool experimental_default_config_file = false;
262263

263264
inline DebugOptions* get_debug_options() { return &debug_options_; }
264265
inline const DebugOptions& debug_options() const { return debug_options_; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"nodeOptions": {
3+
"max-http-header-size": 10
4+
}
5+
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"nodeOptions": {
3+
"max-http-header-size": 20
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"nodeOptions": {
3+
"max-http-header-size": 10
4+
}
5+
}

test/parallel/test-config-file.js

+46
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const { spawnPromisified } = require('../common');
44
const fixtures = require('../common/fixtures');
55
const { match, strictEqual } = require('node:assert');
66
const { test } = require('node:test');
7+
const { chmodSync, constants } = require('node:fs');
8+
const common = require('../common');
79

810
test('should handle non existing json', async () => {
911
const result = await spawnPromisified(process.execPath, [
@@ -304,3 +306,47 @@ test('broken value in node_options', async () => {
304306
strictEqual(result.stdout, '');
305307
strictEqual(result.code, 9);
306308
});
309+
310+
test('should use node.config.json as default', async () => {
311+
const result = await spawnPromisified(process.execPath, [
312+
'--no-warnings',
313+
'--experimental-default-config-file',
314+
'-p', 'http.maxHeaderSize',
315+
], {
316+
cwd: fixtures.path('rc/default'),
317+
});
318+
strictEqual(result.stderr, '');
319+
strictEqual(result.stdout, '10\n');
320+
strictEqual(result.code, 0);
321+
});
322+
323+
test('should override node.config.json when specificied', async () => {
324+
const result = await spawnPromisified(process.execPath, [
325+
'--no-warnings',
326+
'--experimental-default-config-file',
327+
'--experimental-config-file',
328+
fixtures.path('rc/default/override.json'),
329+
'-p', 'http.maxHeaderSize',
330+
], {
331+
cwd: fixtures.path('rc/default'),
332+
});
333+
strictEqual(result.stderr, '');
334+
strictEqual(result.stdout, '20\n');
335+
strictEqual(result.code, 0);
336+
});
337+
// Skip on windows because it doesn't support chmod changing read permissions
338+
test('should throw an error when the file is non readable', { skip: common.isWindows }, async () => {
339+
chmodSync(fixtures.path('rc/non-readable/node.config.json'), constants.O_RDONLY);
340+
const result = await spawnPromisified(process.execPath, [
341+
'--no-warnings',
342+
'--experimental-default-config-file',
343+
'-p', 'http.maxHeaderSize',
344+
], {
345+
cwd: fixtures.path('rc/non-readable'),
346+
});
347+
match(result.stderr, /Cannot read configuration from node\.config\.json: permission denied/);
348+
strictEqual(result.stdout, '');
349+
strictEqual(result.code, 9);
350+
chmodSync(fixtures.path('rc/non-readable/node.config.json'),
351+
constants.S_IRWXU | constants.S_IRWXG | constants.S_IRWXO);
352+
});

test/parallel/test-config-json-schema.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (!common.hasIntl) {
2424
const {
2525
generateConfigJsonSchema,
2626
} = require('internal/options');
27-
const schemaInDoc = require('../../doc/node_config_json_schema.json');
27+
const schemaInDoc = require('../../doc/node-config-schema.json');
2828
const assert = require('assert');
2929

3030
const schema = generateConfigJsonSchema();
@@ -35,6 +35,6 @@ const schema = generateConfigJsonSchema();
3535
// current JSON schema.
3636
// To regenerate the JSON schema, run:
3737
// out/Release/node --expose-internals tools/doc/generate-json-schema.mjs
38-
// And then run make doc to update the out/doc/node_config_json_schema.json file.
38+
// And then run make doc to update the out/doc/node-config-schema.json file.
3939
assert.strictEqual(JSON.stringify(schema), JSON.stringify(schemaInDoc), 'JSON schema is outdated.' +
4040
'Run `out/Release/node --expose-internals tools/doc/generate-json-schema.mjs` to update it.');

tools/doc/generate-json-schema.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ import internal from 'internal/options';
44
import { writeFileSync } from 'fs';
55

66
const schema = internal.generateConfigJsonSchema();
7-
writeFileSync('doc/node_config_json_schema.json', `${JSON.stringify(schema, null, 2)}\n`);
7+
writeFileSync('doc/node-config-schema.json', `${JSON.stringify(schema, null, 2)}\n`);

0 commit comments

Comments
 (0)