Skip to content

Commit c2c819c

Browse files
authored
Safely access environment variables (#2737)
1 parent 9969c45 commit c2c819c

File tree

5 files changed

+90
-2
lines changed

5 files changed

+90
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sumup-oss/circuit-ui": patch
3+
---
4+
5+
Fixed safely accessing environment variables in environments where the `process` variable is undefined.

packages/circuit-ui/components/Display/Display.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { forwardRef, type HTMLAttributes } from 'react';
1818
import { clsx } from '../../styles/clsx.js';
1919
import { CircuitError } from '../../util/errors.js';
2020
import { deprecate } from '../../util/logger.js';
21+
import { getEnvVariable } from '../../util/env.js';
2122

2223
import classes from './Display.module.css';
2324

@@ -75,7 +76,7 @@ export const Display = forwardRef<HTMLHeadingElement, DisplayProps>(
7576
if (
7677
process.env.NODE_ENV !== 'production' &&
7778
process.env.NODE_ENV !== 'test' &&
78-
!process?.env?.UNSAFE_DISABLE_ELEMENT_ERRORS &&
79+
!getEnvVariable('UNSAFE_DISABLE_ELEMENT_ERRORS') &&
7980
!as
8081
) {
8182
throw new CircuitError('Display', 'The `as` prop is required.');

packages/circuit-ui/components/Headline/Headline.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { forwardRef, type HTMLAttributes } from 'react';
1818
import { clsx } from '../../styles/clsx.js';
1919
import { CircuitError } from '../../util/errors.js';
2020
import { deprecate } from '../../util/logger.js';
21+
import { getEnvVariable } from '../../util/env.js';
2122

2223
import classes from './Headline.module.css';
2324

@@ -68,7 +69,7 @@ export const Headline = forwardRef<HTMLHeadingElement, HeadlineProps>(
6869
if (
6970
process.env.NODE_ENV !== 'production' &&
7071
process.env.NODE_ENV !== 'test' &&
71-
!process?.env?.UNSAFE_DISABLE_ELEMENT_ERRORS &&
72+
!getEnvVariable('UNSAFE_DISABLE_ELEMENT_ERRORS') &&
7273
!as
7374
) {
7475
throw new CircuitError('Headline', 'The `as` prop is required.');
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Copyright 2024, SumUp Ltd.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
import { beforeEach, describe, expect, it } from 'vitest';
17+
18+
import { getEnvVariable } from './env.js';
19+
20+
describe('env', () => {
21+
describe('getEnvVariable', () => {
22+
const originalProcess = process;
23+
24+
beforeEach(() => {
25+
process = originalProcess;
26+
process.env = {};
27+
});
28+
29+
it('should return the environment variable`', () => {
30+
process.env.FOO = 'foo';
31+
const actual = getEnvVariable('FOO');
32+
expect(actual).toBe('foo');
33+
});
34+
35+
it('should return undefined if the environment variable is not defined', () => {
36+
const actual = getEnvVariable('FOO');
37+
expect(actual).toBeUndefined();
38+
});
39+
40+
it('should return undefined if `process` is not defined', () => {
41+
// @ts-expect-error We're testing for this error
42+
process = undefined;
43+
const actual = getEnvVariable('FOO');
44+
expect(actual).toBeUndefined();
45+
});
46+
47+
it('should throw an error when used for `NODE_ENV`', () => {
48+
const actual = () => getEnvVariable('NODE_ENV');
49+
expect(actual).toThrowError();
50+
});
51+
});
52+
});

packages/circuit-ui/util/env.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright 2024, SumUp Ltd.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
export function getEnvVariable(name: string) {
17+
if (name === 'NODE_ENV') {
18+
// Some bundlers have special logic for `process.env.NODE_ENV` which
19+
// relies on it being written as a continuous string. Destructuring or
20+
// dynamically accessing `NODE_ENV` can break this logic.
21+
throw new Error('Do not dynamically access NODE_ENV');
22+
}
23+
24+
if (typeof process !== 'undefined') {
25+
return process.env?.[name];
26+
}
27+
28+
return undefined;
29+
}

0 commit comments

Comments
 (0)