Skip to content

Commit

Permalink
Merge pull request #143 from MaxAltena/development
Browse files Browse the repository at this point in the history
Feature: ✨ Introduce `logLevel` to `makeEnvPublic`
  • Loading branch information
HofmannZ authored Jan 14, 2025
2 parents 31dc7d3 + 6b35db8 commit 20f5609
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 17 deletions.
14 changes: 14 additions & 0 deletions src/helpers/log.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ afterAll(() => {
errorSpy.mockRestore();
});

describe('silent', () => {
it('should not log an event message', () => {
error('foo', { logLevel: 'silent' });

expect(errorSpy).not.toHaveBeenCalled();
});

it('should respect log level', () => {
event('foo', { logLevel: 'warn' });

expect(logSpy).not.toHaveBeenCalled();
});
});

describe('error', () => {
it('should log an error message', () => {
error('foo');
Expand Down
49 changes: 39 additions & 10 deletions src/helpers/log.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import { bold, green, red, white, yellow } from '../lib/picocolors';

export type Level = 'error' | 'warn' | 'info';
export type LevelWithSilent = 'silent' | Level;

export interface LogOptions {
/**
* Level of logging
* @default 'event'
*/
logLevel?: LevelWithSilent;
}

export const prefixes = {
error: red(bold('⨯')),
warn: yellow(bold('⚠')),
info: white(bold(' ')),
event: green(bold('✓')),
} as const;
} as const satisfies Record<Level | string, string>;

export const prefixLevels = {
silent: Infinity,
error: 40,
warn: 30,
info: 20,
event: 10,
} as const satisfies Record<keyof typeof prefixes | 'silent', number>;

const suffix = '(next-runtime-env)';

Expand All @@ -15,7 +34,17 @@ const LOGGING_METHOD = {
error: 'error',
} as const;

function prefixedLog(prefixType: keyof typeof prefixes, message: string) {
function prefixedLog(
prefixType: keyof typeof prefixes,
message: string,
options?: LogOptions,
) {
const { logLevel = 'event' } = options || {};

if (prefixLevels[prefixType] < prefixLevels[logLevel]) {
return;
}

const consoleMethod: keyof typeof LOGGING_METHOD =
prefixType in LOGGING_METHOD
? LOGGING_METHOD[prefixType as keyof typeof LOGGING_METHOD]
Expand All @@ -27,18 +56,18 @@ function prefixedLog(prefixType: keyof typeof prefixes, message: string) {
console[consoleMethod](` ${prefix}`, message, suffix);
}

export function error(message: string) {
prefixedLog('error', message);
export function error(message: string, options?: LogOptions) {
prefixedLog('error', message, options);
}

export function warn(message: string) {
prefixedLog('warn', message);
export function warn(message: string, options?: LogOptions) {
prefixedLog('warn', message, options);
}

export function info(message: string) {
prefixedLog('info', message);
export function info(message: string, options?: LogOptions) {
prefixedLog('info', message, options);
}

export function event(message: string) {
prefixedLog('event', message);
export function event(message: string, options?: LogOptions) {
prefixedLog('event', message, options);
}
16 changes: 16 additions & 0 deletions src/utils/make-env-public.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ describe('makeEnvPublic()', () => {

expect(eventMock).toHaveBeenCalledWith(
`Prefixed environment variable 'FOO'`,
undefined,
);

expect(eventMock).toHaveBeenCalledWith(
`Prefixed environment variable 'BAR'`,
undefined,
);

expect(eventMock).toHaveBeenCalledWith(
`Prefixed environment variable 'BAZ'`,
undefined,
);
});

Expand All @@ -72,6 +75,7 @@ describe('makeEnvPublic()', () => {

expect(warnMock).toHaveBeenCalledWith(
`Skipped prefixing environment variable 'FOO'. Variable not in process.env`,
undefined,
);
});

Expand All @@ -82,6 +86,18 @@ describe('makeEnvPublic()', () => {

expect(warnMock).toHaveBeenCalledWith(
`Environment variable 'NEXT_PUBLIC_FOO' is already public`,
undefined,
);
});

it('should not log anything when logLevel is set to silent', () => {
process.env.FOO = 'foo';

makeEnvPublic('FOO', { logLevel: 'silent' });

expect(eventMock).toHaveBeenCalledWith(
`Prefixed environment variable 'FOO'`,
{ logLevel: 'silent' },
);
});
});
26 changes: 19 additions & 7 deletions src/utils/make-env-public.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { event, warn } from '../helpers/log';
import { event, LogOptions, warn } from '../helpers/log';

function prefixKey(key: string) {
export interface MakeEnvPublicOptions extends LogOptions {}

function prefixKey(key: string, options?: MakeEnvPublicOptions) {
// Check if key is available in process.env.
if (!process.env[key]) {
warn(
`Skipped prefixing environment variable '${key}'. Variable not in process.env`,
options,
);

return;
}

// Check if key is already public.
if (/^NEXT_PUBLIC_/i.test(key)) {
warn(`Environment variable '${key}' is already public`);
warn(`Environment variable '${key}' is already public`, options);
}

const prefixedKey = `NEXT_PUBLIC_${key}`;

process.env[prefixedKey] = process.env[key];

// eslint-disable-next-line no-console
event(`Prefixed environment variable '${key}'`);
event(`Prefixed environment variable '${key}'`, options);
}

/**
Expand All @@ -34,12 +37,21 @@ function prefixKey(key: string) {
*
* // Make multiple variables public.
* makeEnvPublic(['FOO', 'BAR', 'BAZ']);
*
* // Disable logging.
* makeEnvPublic('FOO', { logLevel: 'silent' });
*
* // Disable logging in production
* makeEnvPublic('FOO', { logLevel: process.env.NODE_ENV === 'production' ? 'silent': 'info' });
* ```
*/
export function makeEnvPublic(key: string | string[]): void {
export function makeEnvPublic(
key: string | string[],
options?: MakeEnvPublicOptions,
): void {
if (typeof key === 'string') {
prefixKey(key);
prefixKey(key, options);
} else {
key.forEach(prefixKey);
key.forEach((value) => prefixKey(value, options));
}
}

0 comments on commit 20f5609

Please sign in to comment.