Do you guys thought in a way to share or type the ...
# sst
a
Do you guys thought in a way to share or type the environment variables? For example on my Lambda definition in SST, have to declare:
Copy code
environment: {
MY_VAR: 'my value'
}
And then in the function implementation..
Copy code
var MY_VAR = process.env.MY_VAR;
I’m looking for a way to declare the
MY_VAR
definition in a single place, that can avoid any possible renaming issue, or whatever. Also would like to avoid developers to “read” environment variables from random places in the code. I would like to know easily, which are the implemented “inputs” from the environment.
t
You can define a .d.ts file to be included
Copy code
declare global {
      namespace NodeJS {
            interface ProcessEnv {
                  eventBusName: string
            }
      }
}
And this will make it show up under process.env
a
Interesting.
t
I do something a bit different personally - I define a
Config
module that is strongly typed that exports a constant object loaded from SSM
And I don't use env variables at all
a
I’m using config components also, but those reads the env-vars, haha.
Oh I see.
I don’t like env-vars because could be uses in random places.
Found some of the devs reading them really deep in the code, and is not easy to track.
I’m looking to a “config” thing as you said.
I do use SSM too, but sometimes sending env-vars for SSM-Middy to read them.
Do you have example of this? or you built something totally out of your mind?
t
I do something kinda crazy haha
My only example is from a shared library I use across my projects
Copy code
import { SSM } from "aws-sdk"
import deasync from "deasync"

const ssm = new SSM()

export interface ConfigType {
  STAGE: string
  BUS_NAME: string
  STRIPE_KEY: string
  USER_POOL_ID: string
  SLACK_WEBHOOK_URL: string
}

export const Config: ConfigType = {} as any

function refresh(cb: any) {
  const time = Date.now()
  const { SSM_PATH, APP_NAME } = process.env
  if (!SSM_PATH) throw new Error("SSM_PATH is not defined")
  if (!APP_NAME) throw new Error("APP_NAME is not defined")

  function get(next?: string) {
    ssm.getParametersByPath(
      {
        Path: SSM_PATH!,
        Recursive: true,
        NextToken: next,
      },
      (err, result) => {
        if (err) throw err
        const values = result.Parameters!.reduce((collect, item) => {
          if (!item.Name!.includes("ship") && !item.Name!.includes(APP_NAME!))
            return collect
          const splits = item.Name!.split("/")
          const key = splits.pop()!
          collect[key] = item.Value!
          return collect
        }, {} as Record<string, string>)
        Object.assign(Config, values)
        if (result.NextToken) {
          get(result.NextToken)
          return
        }
        cb()
      }
    )
  }
  get(undefined)
}

deasync(refresh)()
that type is for shared resources across my apps. And then they can extend this type with their own stuff by declaring it in a
.d.ts
file
Copy code
import { ConfigType } from "@ironbay/ship"
declare module "@ironbay/ship" {
  interface ConfigType {
    MYSQL_HOST: string
    MYSQL_USER: string
    MYSQL_PASSWORD: string
    MYSQL_SSL: string
    APPSYNC_URL: string
    APPSYNC_KEY: string
  }
}
the crazy part is I use
deasync
lol to freeze the node process until the call to SSM is done
a
Interesting, let’s check it.