Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: add built-in .env file support #48890

Merged
merged 15 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixup! feat: add NODE_OPTIONS support to .env
  • Loading branch information
anonrig committed Aug 13, 2023
commit c0a6c51b0b2416134368464869db67061a500b66
13 changes: 8 additions & 5 deletions src/node_dotenv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ using v8::String;

std::optional<std::string> Dotenv::GetPathFromArgs(
const std::vector<std::string>& args) {
std::string flag = "--env-file";
std::string_view flag = "--env-file";
// Match the last `--env-file`
// This is required to imitate the default behavior of Node.js CLI argument
// matching.
auto path =
MoLow marked this conversation as resolved.
Show resolved Hide resolved
std::find_if(args.begin(), args.end(), [&flag](const std::string& arg) {
return strncmp(arg.c_str(), flag.c_str(), flag.size()) == 0;
std::find_if(args.rbegin(), args.rend(), [&flag](const std::string& arg) {
return strncmp(arg.c_str(), flag.data(), flag.size()) == 0;
});

if (path == args.end()) {
if (path == args.rend()) {
return std::nullopt;
}

Expand All @@ -28,7 +31,7 @@ std::optional<std::string> Dotenv::GetPathFromArgs(

auto next_arg = std::next(path);

if (next_arg == args.end()) {
if (next_arg == args.rend()) {
return std::nullopt;
}

Expand Down
59 changes: 0 additions & 59 deletions test/parallel/test-dotenv-node-options.js
anonrig marked this conversation as resolved.
Outdated
Show resolved Hide resolved

This file was deleted.

88 changes: 88 additions & 0 deletions test/parallel/test-dotenv-node-options.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { spawnPromisified } from '../common/index.mjs';
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';

const __dirname = fileURLToPath(new URL('.', import.meta.url));
const validEnvFilePath = '../fixtures/dotenv/valid.env';
const relativePath = '../fixtures/dotenv/node-options.env';

describe('.env supports NODE_OPTIONS', () => {
anonrig marked this conversation as resolved.
Show resolved Hide resolved

it('should have access to permission scope', async () => {
const code = `
require('assert')(process.permission.has('fs.read'));
`.trim();
const child = await spawnPromisified(process.execPath,
[ `--env-file=${relativePath}`, '--eval', code ], {
cwd: __dirname
});
// Test NODE_NO_WARNINGS environment variable
// `stderr` should not contain "ExperimentalWarning: Permission is an experimental feature" message
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

it('validate only read permissions are enabled', async () => {
const code = `
require('fs').writeFileSync(require('path').join(__dirname, 'should-not-write.txt'), 'hello', 'utf-8')
`.trim();
const child = await spawnPromisified(process.execPath,
[ `--env-file=${relativePath}`, '--eval', code ], {
cwd: __dirname,
});
assert.match(child.stderr, /Error: Access to this API has been restricted/);
assert.match(child.stderr, /code: 'ERR_ACCESS_DENIED'/);
assert.match(child.stderr, /permission: 'FileSystemWrite'/);
assert.strictEqual(child.code, 1);
});

it('TZ environment variable', async () => {
const code = `
require('assert')(new Date().toString().includes('Hawaii'))
`.trim();
const child = await spawnPromisified(process.execPath,
[ `--env-file=${relativePath}`, '--eval', code ], {
cwd: __dirname,
});
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

it('should update UV_THREADPOOL_SIZE', async () => {
const code = `
require('assert').strictEqual(process.env.UV_THREADPOOL_SIZE, '5')
`.trim();
const child = await spawnPromisified(process.execPath,
[ `--env-file=${relativePath}`, '--eval', code ], {
cwd: __dirname,
});
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

it('should use the last --env-file declaration', async () => {
const code = `
require('assert').strictEqual(process.env.BASIC, 'basic');
`.trim();
const child = await spawnPromisified(process.execPath,
[ `--env-file=${relativePath}`, `--env-file=${validEnvFilePath}`, '--eval', code ], {
cwd: __dirname,
});
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

it('should handle unexisting .env file', async () => {
const code = `
require('assert').strictEqual(1, 1)
`.trim();
const child = await spawnPromisified(process.execPath,
[ '--env-file=.env', '--eval', code ], {
cwd: __dirname,
});
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

});