Blog
sanitizeEnvVars function in Storybook codebase.

sanitizeEnvVars function in Storybook codebase.

In this article, we review sanitizeEnvVars function in Storybook codebase. We will look at:

  1. sanitizeEnvVars function

I study patterns used in an open source project found on Github Trending. For this week, I reviewed some parts of Storybook codebase and wrote this article.

sanitizeEnvVars function

You will find the following definition in storybook/code/builders/builder-vite/src/envs.ts.

// Sanitize environment variables if needed
export async function sanitizeEnvVars(options: Options, config: ViteConfig) {
  const { presets } = options;
  const envsRaw = await presets.apply<Promise<Builder_EnvsRaw>>('env');
  let { define } = config;
  if (Object.keys(envsRaw).length) {
    // Stringify env variables after getting `envPrefix` from the  config
    const envs = stringifyProcessEnvs(envsRaw, config.envPrefix);
    define = {
      ...define,
      ...envs,
    };
  }
  return {
    ...config,
    define,
  } as ViteConfig;
}

stringifyProcessEnvs 

stringifyProcessEnvs is defined at L22 in the same file and is defined as following:

/**
 * Customized version of stringifyProcessEnvs from storybook/internal/core-common which uses
 * import.meta.env instead of process.env and checks for allowed variables.
 */
export function stringifyProcessEnvs(raw: Builder_EnvsRaw, envPrefix: ViteConfig['envPrefix']) {
  const updatedRaw: Builder_EnvsRaw = {};
  const envs = Object.entries(raw).reduce((acc: Builder_EnvsRaw, [key, value]) => {
    // Only add allowed values OR values from array OR string started with allowed prefixes
    if (
      allowedEnvVariables.includes(key) ||
      (Array.isArray(envPrefix) && !!envPrefix.find((prefix) => key.startsWith(prefix))) ||
      (typeof envPrefix === 'string' && key.startsWith(envPrefix))
    ) {
      acc[`import.meta.env.${key}`] = JSON.stringify(value);
      updatedRaw[key] = value;
    }
    return acc;
  }, {});
  // support destructuring like
  // const { foo } = import.meta.env;
  envs['import.meta.env'] = JSON.stringify(stringifyEnvs(updatedRaw));

  return envs;
}

Then this function is also calling another function named stringifyEnvs and it is defined in common/utils/envs.ts.

export const stringifyEnvs = (raw: Record<string, string>): Record<string, string> =>
  Object.entries(raw).reduce<Record<string, string>>((acc, [key, value]) => {
    acc[key] = JSON.stringify(value);
    return acc;
  }, {});

About me:

Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.

Email: ramu.narasinga@gmail.com

Study the patterns used in large OSS projects at Think Throo.

References:

  1. https://github.com/storybookjs/storybook/blob/next/code/builders/builder-vite/src/envs.ts#L44

  2. https://github.com/storybookjs/storybook/blob/next/code/builders/builder-vite/src/envs.ts#L22