Fatima Logofatima

Building your own loader

Fatima is completely agnostic on how you load your secrets.

There's currently some built-in loaders that you can use, but I will show you how to create your own.

Do not proceed on your own with these providers

Unless you know what you're doing, I highly recommend using the built-in loaders for the following providers:

  • Vercel
  • Trigger.dev (the extension is the hard part)

How the load object works

Inside your env.config.ts there's an available load key that you can fill with an object of the following type:

types.d.ts
export type UnsafeEnvironmentVariables = Record<string, string>;
 
export type FatimaLoadFunction = () => Promisable<
  UnsafeEnvironmentVariables | null | undefined
>;
 
export type FatimaLoaderChain = FatimaLoadFunction[] | FatimaLoadFunction;
 
export type FatimaLoader = {
  development: FatimaLoaderChain;
  [nodeEnv: string]: FatimaLoaderChain;
};

This means you can pass multiple loaders for specific environments based on the environment key.

When chain loading your load functions, Fatima will execute them in order, and progressively merge the results, so what's loaded before will be available for the next loader.

The development key is mandatory, it will be used when running fatima dev.

And yeah, this means you can load secrets from any source, .env or cloud.

Creating a custom load function with the InfisicalSDK

Info

Fatima alredy comes with a built-in infisical loader, this is just an example.

We will be using the built-in dotenv loader to load from .env. It is just a dumb wrapper around dotenv.

env.config.ts
import { config, adapters, UnsafeEnvironmentVariables } from "fatima";
import dotenv from "dotenv";
 
export default config({
  load: {
    development: [
      adapters.dotenv.load(dotenv),
      async () => {
        // All of the process.env were loaded by the previous dotenv loader
 
        const client = new infisicalClient();
 
        await client.auth().universalAuth.login({
          clientId: process.env.INFISICAL_CLIENT_ID!,,
          clientSecret: process.env.INFISICAL_CLIENT_SECRET!,
        });
 
        const { secrets } = await client.secrets().listSecrets({
          projectId: process.env.INFISICAL_PROJECT_ID!,
          environment: "dev",
        });
 
        const env = secrets.reduce((acc, { secretKey, secretValue }) => {
          acc[secretKey] = secretValue;
          return acc;
        }, {} as UnsafeEnvironmentVariables);
 
        return env;
      },
    ],
  },
});

Any loader will work as long as it returns a UnsafeEnvironmentVariables object.

On this page